类&构造函数
9.1 通常情况,使用class
。避免直接操作prototype
为什么?
class
语法更简洁且更好理解
// bad
function Queue(contents=[]){
this.queue=[...contents]
}
Queue.prototype.pop=function(){
const value=this.queque[0]
this.queque.splice(0,1)
return value
}
// good
class Queue{
constructor(contents=[]){
this.queue=[...contents]
}
pop(){
const value=this.queue[0]
this.queue.splice(0,1)
return value
}
}
9.2使用extends
来继承
为什么?它是一个内置的继承原型的方法,而且它不会破坏
instanceof
// bad
const inherits = require('inherits');
function PeekableQueue(contents) {
Queue.apply(this, contents);
}
inherits(PeekableQueue, Queue);
PeekableQueue.prototype.peek = function () {
return this.queue[0];
};
// good
class PeekableQueue extends Queue {
peek() {
return this.queue[0];
}
}
9.3方法可以返回this
来进行方法的链式调用
// bad
Jedi.prototype.jump = function () {
this.jumping = true;
return true;
};
Jedi.prototype.setHeight = function (height) {
this.height = height;
};
const luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20); // => undefined
// good
class Jedi {
jump() {
this.jumping = true;
return this;
}
setHeight(height) {
this.height = height;
return this;
}
}
const luke = new Jedi();
luke.jump()
.setHeight(20);
9.4自定义一个toString()
方法是可以的,但是要确保它能正确运行且没有副作用
class Jedi{
constructor(options={}) {
this.name=options.name||'no name'
}
getName() {
return this.name
}
toString() {
return `Jedi - ${this.getName()}`
}
}
9.5类如果没有定义一个构造函数,它会有一个默认的构造函数。如果是一个空的构造函数或者是继承自父类的构造函数,就没必要去定义它
eslint: no-useless-constructor
// bad
class Jedi {
constructor() {}
getName() {
return this.name;
}
}
// bad
class Rey extends Jedi {
constructor(...args) {
super(...args);
}
}
// good
class Rey extends Jedi {
constructor(...args) {
super(...args);
this.name = 'Rey';
}
}
9.6避免类成员重复
eslint: no-dupe-class-members
为什么?类成员声明重复,会静默的以最后一个为准-存在重复的情况基本可以判定是有bug的
// bad
class Foo {
bar() { return 1; }
bar() { return 2; }
}
// good
class Foo {
bar() { return 1; }
}
// good
class Foo {
bar() { return 2; }
}