JavaScript中prototype与constructor疑问:代码输出为何两次都是A?
为什么JavaScript原型继承中constructor属性指向不符合预期?
先看这段代码:
function A(){} function B(){} function C(){} B.prototype = new A(); console.log(B.prototype.constructor); C.prototype = new B(); console.log(C.prototype.constructor);
实际运行后的输出是:
[Function: A]
[Function: A]
但你预期的输出是:
[Function: A]
[Function: B]
这完全是原型继承里一个容易踩的小坑,咱们一步步说清楚:
当你执行
B.prototype = new A()时,B.prototype被替换成了A的实例对象。而这个实例的constructor属性是从A.prototype继承来的——默认情况下,A.prototype.constructor就是构造函数A本身。因为你没手动修改B.prototype.constructor,所以它自然指向A。到了
C.prototype = new B(),C.prototype变成了B的实例。但B的实例的constructor属性是沿着原型链找的:B的原型已经是A的实例,所以B实例会顺着原型链找到A.prototype.constructor,也就是A。所以第二次输出还是A。
简单说就是:当你替换构造函数的prototype对象时,新的prototype(是另一个构造函数的实例)不会自动把constructor指向当前构造函数,它会保留原型链上层的constructor指向。
如果要得到你预期的结果,只需要在替换prototype后手动修正constructor指向:
function A(){} function B(){} function C(){} B.prototype = new A(); B.prototype.constructor = B; // 手动修正constructor指向 console.log(B.prototype.constructor); // 此时输出[Function: B] C.prototype = new B(); C.prototype.constructor = C; // 同样修正 console.log(C.prototype.constructor); // 输出[Function: C]
另外补充个小知识点:现在更推荐用Object.create()来实现原型继承,这样可以避免调用父构造函数带来的不必要副作用,同样记得修正constructor:
B.prototype = Object.create(A.prototype); B.prototype.constructor = B;
内容的提问来源于stack exchange,提问作者Felix
相关产品推荐
相关产品推荐

