原型继承未按预期工作
Prototype inheritance is not working as expected
从我的 JavaScript 童年开始,我就阅读并遵循了在原型继承的情况下我应该重写构造函数。但令我惊讶的是,即使注释了重写的构造函数语句,以下示例也会在控制台输出相同的内容。请指教
function A() {
console.info("A constructor");
}
function B() {
console.info("B constructor");
}
B.prototype = A.prototype;
B.prototype.constructor = B; // Do we really need this statement?
console.info("cp 1");
var b = new B();
console.info("cp 2");
在进入构造函数部分之前,您的代码中存在问题。您正在使 B.prototype
和 A.prototype
相同,方法是
B.prototype = A.prototype;
这意味着,您无法有效识别这些函数构造的对象的父级。试试这个
console.log(new B() instanceof A, new B() instanceof B);
// true true
这是预料之中的,因为 B
是由 B
创建的,而 B
是根据 A
的原型创建的。但是
console.log(new A() instanceof A, new A() instanceof B);
// true true
什么?为什么 A
的对象是 B
的实例?因为,既然你让 B.prototype
也和 A.prototype
一样,当一个对象 A
试图找出它的原型(A.prototype
是从 A
) 存在于 B
的原型链中的任何地方。由于 B.prototype
与 A.prototype
相同,因此可以将 A
的对象视为 B
的对象。
正确的做法是,
B.prototype = Object.create(A.prototype);
现在,您正在使 B
的原型成为使用 A
的原型创建的对象。所以,它不是A
'原型,而是基于A
.
原型创建的对象
现在,如果我们不这样做会怎样
B.prototype.constructor = B;
尝试打印由 B
创建的对象的 constructor
属性,不包含该行
console.log((new B()).constructor);
// [Function: A]
由于 B
的原型仍然具有从 A
的 prototype
复制的构造函数值,它仍然引用函数 A
。这就是我们用 B
函数对象替换它的原因。
从我的 JavaScript 童年开始,我就阅读并遵循了在原型继承的情况下我应该重写构造函数。但令我惊讶的是,即使注释了重写的构造函数语句,以下示例也会在控制台输出相同的内容。请指教
function A() {
console.info("A constructor");
}
function B() {
console.info("B constructor");
}
B.prototype = A.prototype;
B.prototype.constructor = B; // Do we really need this statement?
console.info("cp 1");
var b = new B();
console.info("cp 2");
在进入构造函数部分之前,您的代码中存在问题。您正在使 B.prototype
和 A.prototype
相同,方法是
B.prototype = A.prototype;
这意味着,您无法有效识别这些函数构造的对象的父级。试试这个
console.log(new B() instanceof A, new B() instanceof B);
// true true
这是预料之中的,因为 B
是由 B
创建的,而 B
是根据 A
的原型创建的。但是
console.log(new A() instanceof A, new A() instanceof B);
// true true
什么?为什么 A
的对象是 B
的实例?因为,既然你让 B.prototype
也和 A.prototype
一样,当一个对象 A
试图找出它的原型(A.prototype
是从 A
) 存在于 B
的原型链中的任何地方。由于 B.prototype
与 A.prototype
相同,因此可以将 A
的对象视为 B
的对象。
正确的做法是,
B.prototype = Object.create(A.prototype);
现在,您正在使 B
的原型成为使用 A
的原型创建的对象。所以,它不是A
'原型,而是基于A
.
现在,如果我们不这样做会怎样
B.prototype.constructor = B;
尝试打印由 B
创建的对象的 constructor
属性,不包含该行
console.log((new B()).constructor);
// [Function: A]
由于 B
的原型仍然具有从 A
的 prototype
复制的构造函数值,它仍然引用函数 A
。这就是我们用 B
函数对象替换它的原因。