浏览 1194
扫码
类
ES2015/ES6 类优先与 ES5 纯函数
很难为经典的 ES5 类创建可读的的继承、 构造和方法定义。 如果你需要继承(并且感到奇怪为啥你不需
要), 则优先用 ES2015/ES6的类。 不过, 短小的函数优先于类, 知道你发现你需要更大并且更复杂的
对象。
不好的:
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() {};
好的
class Animal {constructor(age) {this.age = age;}move() { /* ... */ }}class Mammal extends Animal {constructor(age, furColor) {super(age);this.furColor = furColor;}liveBirth() { /* ... */ }}class Human extends Mammal {constructor(age, furColor, languageSpoken) {super(age, furColor);this.languageSpoken = languageSpoken;}speak() { /* ... */ }}
使用方法链
这个模式在 JavaScript 中是非常有用的, 并且你可以在许多类库比如 jQuery 和 Lodash 中见到。
它允许你的代码变得富有表现力, 并减少啰嗦。 因为这个原因, 我说, 使用方法链然后再看看你的代码
会变得多么简洁。 在你的类/方法中, 简单的在每个方法的最后返回 this , 然后你就能把这个类的
其它方法链在一起。
不好的:
class Car {constructor() {this.make = 'Honda';this.model = 'Accord';this.color = 'white';}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();car.setColor('pink');car.setMake('Ford');car.setModel('F-150');car.save();
好的:
class Car {constructor() {this.make = 'Honda';this.model = 'Accord';this.color = 'white';}setMake(make) {this.make = make;// NOTE: Returning this for chainingreturn this;}setModel(model) {this.model = model;// NOTE: Returning this for chainingreturn this;}setColor(color) {this.color = color;// NOTE: Returning this for chainingreturn this;}save() {console.log(this.make, this.model, this.color);// NOTE: Returning this for chainingreturn this;}}const car = new Car().setColor('pink').setMake('Ford').setModel('F-150').save();
组合优先于继承
正如设计模式四人帮所述, 如果可能,
你应该优先使用组合而不是继承。 有许多好的理由去使用继承, 也有许多好的理由去使用组合。这个格言
的重点是, 如果你本能的观点是继承, 那么请想一下组合能否更好的为你的问题建模。 很多情况下它真的
可以。
You might be wondering then, “when should I use inheritance?” It
depends on your problem at hand, but this is a decent list of when inheritance
makes more sense than composition:
那么你也许会这样想, “我什么时候改使用继承?” 这取决于你手上的问题, 不过这儿有一个像样的列表说
明什么时候继承比组合更好用:
- 你的继承表示”是一个”的关系而不是”有一个”的关系(人类->动物 vs 用户->用户详情);
- 你可以重用来自基类的代码(人可以像所有动物一样行动);
- 你想通过基类对子类进行全局的修改(改变所有动物行动时的热量消耗);
不好的:
class Employee {constructor(name, email) {this.name = name;this.email = email;}// ...}// 不好是因为雇员“有”税率数据, EmployeeTaxData 不是一个 Employee 类型。class EmployeeTaxData extends Employee {constructor(ssn, salary) {super();this.ssn = ssn;this.salary = salary;}// ...}
好的:
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);}// ...}