JS中原型对象中的constructor的作用?

最近被同事问道一个问题:

function Father() {
    this.color = ['red', 'green'];
  }
  function Child() {
    this.test = 1;
  }

  Child.prototype = new Father();

  let instance = new Child();

这个例子是经典原型链继承,未做constructor修复的一个例子。
问:
instance的属性test哪里来的,要知道这里的此时instance的构造函数instance.constructor是Father,我们再根据一般Java,ES6类中的构造函数的拷贝属性用法,instance的属性要有也是Father的color?

问题就在这里了,js的new并不像Java 这种OOP语言的new一样,js的new后面的不是类,就是普通函数,普通函数以new调用,内部过程为:MDN,New
test的属性是通过this的改变获取到的,压根没走js原型对象中的constructor。所以这里就是一个误区。

那么js原型对象中的constructor有什么作用?上面的继承让我们instance.color通过原型链访问到了Father的color属性,最后为什么一般要修复Child.prototype.constructor = Child呢。

答案其实也没那么重要:

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

目前看到的作用之一,通过实例的构造函数给闭包中的函数增加属性方法。

var a,b;
(function(){
  function A (arg1,arg2) {
    this.a = 1;
    this.b=2; 
  }

  A.prototype.log = function () {
    console.log(this.a);
  }
  a = new A();
  b = new A();
})()
a.log();
// 1
b.log();
// 1

通过以上代码我们可以得到两个对象,a,b,他们同为类A的实例。因为A在闭包里,所以现在我们是不能直接访问A的,那如果我想给类A增加新方法怎么办?

// a.constructor.prototype 在chrome,firefox中可以通过 a.__proto__ 直接访问
a.constructor.prototype.log2 = function () {
  console.log(this.b)
}

a.log2();
// 2
b.log2();
// 2

通过访问constructor就可以了。
在这里插入图片描述
这位老哥的解释也就是上面的代码的一个应用了。

不过你拿到 prototype 也不见得能拿到 正确的 constructor,JS没有提供方式确保你拿到“正确”的
constructor。我们只能根据惯例相信对象上的 constructor 应该是“正确”的 constructor。

这也是我们上面做constructor修复的一个原因了。

参考:
知乎
红宝石书

posted @ 2019-12-24 22:15  Lawliet__zmz  阅读(3252)  评论(0编辑  收藏  举报