关于 “JavaScript重写原型对象后设置constructor” 的误解

首先我们要知道prototype、constructor及其关系:

  • 每个函数都有 prototype属性(即原型对象)
  • 原型对象都有 constructor属性(指针):它指向着该原型对象的拥有者。

现在看下面例子:

function Child() {}
Child.prototype = {};   //重写prototype
Child.prototype.constructor = Child;
误解:

之所以执行Child.prototype.constructor = Child,是因为:
我们重写了Child的prototype,导致prototype的constructor指向发生了改变,因而要让其指向正确的位置。

正解:

之所以执行Child.prototype.constructor = Child,是因为:
constructor是原型对象特有的属性,所以在我们将一个空对象赋给了prototype后,prototype对象压根就没有constructor属性(都没有,谈何改变呢?)
执行第三句仅仅是为了为prototype增加constructor属性,并规定其正确的指向。

如果在没有执行Child.prototype.constructor = Child的情况下,强行访问constructor,那访问的便是其 父级原型(沿着原型链找)的constructor所指向的值:

function Child2() {}
Child2.prototype = {};   //重写prototype
console.log(Child2.prototype.constructor);     //ƒ Object() { [native code] }

在Child2.prototype没有constructor属性的前提下, 又要得到Child2.prototype.constructor的值,那只好沿着原型链找,看看它的父级(Object)有没有constructor属性,发现:“啊有!!”
所以Child2.prototype.constructor的值为 ƒ Object() { [native code] },即指向Object()


总结:
  • 只有prototype才有constructor属性,而其他实例对象没有。(不考虑继承)
  • 若完全重写prototype,需要为重写后的prototype增加constructor属性,并规定其正确的指向。

我们再看一个例子:

function Parent () {
    this.name = 'bty';
}
function Child () {}

(1)我们再执行:

console.log(new Parent());
console.log(Child.prototype);

在控制台输出:
在这里插入图片描述
我们看到此时Parent构造函数new出的实例没有constructor属性(不考虑继承),而Child.prototype有。
这也印证了上面的话:只有prototype才有constructor属性,而其他实例对象没有(不考虑继承)

(2)再接着,我们让Child继承Parent,并打印Child的原型对象:

Child.prototype = new Parent();
console.log(Child.prototype);

在控制台输出:
在这里插入图片描述
和new Parent()的输出结果一模一样,没有constructor属性。

(3)继续,我们为Child.prototype添加constructor属性并规定其指向,然后再打印Child的原型对象:

Child.prototype.constructor = Child;
console.log(Child.prototype);

控制台输出:
在这里插入图片描述

添加成功,Child.prototype的constructor指向Child


实现继承时为何总是要修正constructor的指向呢?

在知乎的一篇问答中看到一种说法:

constructor其实没有什么用处,只是JavaScript语言设计的历史遗留物。由于constructor属性是可以变更的,所以未必真的指向对象的构造函数,只是一个提示。不过,从编程习惯上,我们应该尽量让对象的constructor指向其构造函数,以维持这个惯例。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值