你应该使用__proto__
继承的风格。这假设您只为 Node 编写代码,或者只支持您最喜欢的浏览器。此外,Base.call(this)
如果您关心基本原型的构造函数中的任何逻辑,则这是必要的。
引用基本原型的__proto__
技术将确保instanceof
操作员正确识别原型的实例。.constructor
子类实例的属性将引用您期望的构造函数。它还具有不实例化基本原型的新实例的好处。
该new Base()
样式还将确保instanceof
为您提供正确的答案,但它将运行 Base 的构造函数。通常不是问题,但如果您的基本构造函数具有必需的参数,则可能会出现问题。它还将.constructor
属性设置为基本构造函数,而不是后代构造函数。
将类的原型设置为基类的原型会造成混淆instanceof
,因为基类的任何后代也似乎是子类的实例。
像泥一样清澈,对吧?这个例子应该有帮助:
// Base constructor.
// A, B, and C will inherit from Base.
function Base() {
this.name = 'base';
}
// new Base() style
function A() {
Base.call(this);
}
A.prototype = new Base();
// __proto__ = prototype style
function B() {
Base.call(this);
}
B.prototype.__proto__ = Base.prototype;
// prototype = protoype style
function C() {
Base.call(this);
}
C.prototype = Base.prototype;
// create instances
var a = new A();
var b = new B();
var c = new C();
// are we who we think we are?
console.assert(a instanceof A);
console.assert(b instanceof B);
console.assert(c instanceof C);
// so far so good
// do we respect our elders?
console.assert(a instanceof Base);
console.assert(b instanceof Base);
console.assert(c instanceof Base);
// we have respect
// test to see that Base.call(this)
// functioned as expected
console.assert(a.name == 'base');
console.assert(b.name == 'base');
console.assert(c.name == 'base');
// ok, good...
// but now things get weird
console.assert(a instanceof C);
console.assert(b instanceof C);
// that's not right! a is not C, b is not C!
// At least A and B do not confuse identities
console.assert(!(a instanceof B));
console.assert(!(b instanceof A));
console.assert(!(c instanceof A));
console.assert(!(c instanceof B));
// so we've determined that style C is no good.
// C confuses the inheritance chain.
// B is the winner.
// Why? Only B passes this test
console.assert(b.constructor == B);
// a and c's constructors actually point to the Base constructor
console.assert(a.constructor == Base);
console.assert(c.constructor == Base);
// Word B.