一、优先使用ES6语法的类而不是ES5的纯函数
传统的ES5类语法很难拥有类的继承、构造函数和方法的定义。如果你需要使用继承(要注意的是,你可能不需要),那么就用ES2015/ES6的类。但是,在你发现你需要更大更复杂的对象的之前,尽量使用小巧的函数。
Bad: const Animal = function(age) { if (!(this instanceof Animal)) { throw new Error(‘Instantiate Animal with `new`‘); } this.age = age; }; Animal.prototype.move = function move() {}; const Mammal = function(age, furColor) { if (!(this instanceof Mammal)) { throw new Error(‘Instantiate Mammal with `new`‘); } Animal.call(this, age); this.furColor = furColor; }; Mammal.prototype = Object.create(Animal.prototype); Mammal.prototype.constructor = Mammal; Mammal.prototype.liveBirth = function liveBirth() {}; const Human = function(age, furColor, languageSpoken) { if (!(this instanceof Human)) { throw new Error(‘Instantiate Human with `new`‘); } Mammal.call(this, age, furColor); this.languageSpoken = languageSpoken; }; Human.prototype = Object.create(Mammal.prototype); Human.prototype.constructor = Human; Human.prototype.speak = function speak() {}; Good: //定义一个动物类,有age属性和move方法 class Animal { constructor(age) { this.age = age; } move() { /* ... */ } } //定义一个哺乳动物类继承动物类,除了animal的属性和方法外还有自己的liveBirth方法 class Mammal extends Animal { constructor(age, furColor) { super(age); this.furColor = furColor; } liveBirth() { /* ... */ } } //定义人类这个类继承哺乳动物,除哺乳动物的属性和方法外,还有自己的languageSpoken属性和speak方法 class Human extends Mammal { constructor(age, furColor, languageSpoken) { super(age, furColor); this.languageSpoken = languageSpoken; } speak() { /* ... */ } }
二、使用方法链
这个模式在JS中非常有用,你可以在很多像jquery、lodash等库中看到。它可以让你的代码简洁而富有表现力。正是因为这个原因,所以我说使用方法链,然后看下你的代码可以变得多么简洁。在你的类函数中,在每个函数的最后简单的返回this,你就可以把这个类的方法链在一起。
Bad: class Car { constructor(make, model, color) { this.make = make; this.model = model; this.color = color; } setMake(make) { this.make = make; } setModel(model) { this.model = model; } setColor(color) { this.color = color; } save() { console.log(this.make, this.model, this.color); } } const car = new Car(‘Ford‘,‘F-150‘,‘red‘); car.setColor(‘pink‘); car.save(); Good: class Car { constructor(make, model, color) { this.make = make; this.model = model; this.color = color; } setMake(make) { this.make = make; // 为链式调用返回this return this; } setModel(model) { this.model = model; // 为链式调用返回this return this; } setColor(color) { this.color = color; // 为链式调用返回this return this; } save() { console.log(this.make, this.model, this.color); // 为链式调用返回this return this; } } //链式调用 const car = new Car(‘Ford‘,‘F-150‘,‘red‘) .setColor(‘pink‘) .save();
三、优先使用组合而不是继承
正如著名的设计模式(Design Patterns )所论述的一样,你应该尽可能的使用组合而不是继承。使用组合和继承的优点都有很多。这则论述的主要观点是:如果你本来想用继承,那么想想组合能不能替代,大部分情况下都是可以的。
你可能会想,什么时候我需要使用继承呢?这取决于你手头的问题,这有个列表说明什么时候使用继承比使用组合好:
1、你的继承代表的“是一个”的关系而不是“有一个”的关系。(人类继承自动物,用户有用户明细Human->Animal vs. User->UserDetails)
2、你可以重用基类的代码。(人类像动物一样拥有move方法)
3、你想要通过改变积累来全局(改变子类继承自基类的方法)(改变动物运动时的热量消耗)
Bad: class Employee { constructor(name, email) { this.name = name; this.email = email; } // ... } //不好是因为EmployeeTaxData 并不是Employee 的一种类型。而是Employee 有EmployeeTaxData 。 class EmployeeTaxData extends Employee { constructor(ssn, salary) { super(); this.ssn = ssn; this.salary = salary; } // ... } Good: class EmployeeTaxData { constructor(ssn, salary) { this.ssn = ssn; this.salary = salary; } // ... } class Employee { constructor(name, email) { this.name = name; this.email = email; } //员工有税率数据 setTaxData(ssn, salary) { this.taxData = new EmployeeTaxData(ssn, salary); } // ... }
时间: 2024-11-08 10:07:40