javascript中,constructor.prototype.constructor 为什么会不是Object()

1、一个通过new创造的instance,他的constructor.prototype.constructor为什不是Object()

2、实例代码如下:

function Dog(name){
    this.name = name;
}

var dog1 = new Dog('dg1')

dog1.constructor.prototype.constructor // Dog()

疑问:如上代码,我的理解是constructor.prototype 是一个普通的对象,所以这个普通的对象的constructor应该是Object(),而不是Dog()

4、再看如下代码:

function Dog(name){
    this.name = name;
}

Dog.prototype = {
    color:'black',
    age:3
}

var dog2 = new Dog('dg2')

dog2.constructor.prototype.constructor // Object()

疑问:这里返回的是符合预期的Object(),难道一个构造函数默认的prototype不是一个普通的空对象么?或者说跟我们手动赋值的自定义对象有差别?这里的疑问一直没搞明白,希望各路神仙指点~~

阅读 4.8k
5 个回答

em...感觉你原型对象弄混了...

构造函数的实例本身是没有constructor的,它的constructor继承自原型,原型的constructor指向构造函数,所以dog1.constructor === Dog。这里不能跳过dog1先看后边的。

看懂的话继续..
原题变为Dog.prototype.constructor
Dog.prototype指向的是Dog构造函数的原型对象
所以最后的问题变为:原型对象的constructor,那不就是构造函数么,也就是Dog,没毛病啊..

看懂的话再继续..
至于第二个例子,你的原型对象指向一个另一个对象了,constructor自然不指向原来的构造函数了,而是指向Object构造函数。

可以看一下我写的文章,里边有原型对象的关系图,一看你就知道问题出在哪了。JS基础—原型对象的那些事(二)

无论什么时候,只要创建了一个函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。在默认情况下,所有对象原型都会自动获得一个constructor属性,这个属性包含一个指向prototype属性所在函数的指针。 --Javascript高级程序设计

dog1.constructor指向Dog,所以例一Dog.prototype.constructor默认指向Dog。例二修改了Dog.prototype的指向,指向了一个普通对象,和你理解的一样。

你说的没错,constructor.prototype 的确是一个对象,它的构造器也的确应该是 Object。

但是,constructor.prototype 是一个特殊的对象,它不普通,它决定了构造出来的 instance 会存在哪些方法和属性。

如果 instance.constructor.prototype.constructor === Object, 那么instance就没法正确获取到它的constructor了!

obj.constructor 往往会指向这个对象的构造器,但是它能工作的原因是因为 obj 的原型上有 constructor. obj.constructor ---> Object.getPrototypeOf(obj).constructor, obj.hasOwnProperty('constructor') === false, obj本身是没有constructor属性的。

但是如果 obj 是构造函数的 prototype对象,也就是 constructor.prototype.constructor, 就必须指回这个构造函数,constructor.prototype.constructor === constructor,否则这些constructor 构造出来的 instance 的 constructor 属性就没法工作了。

构造器默认的 prototype 对象就是一个只有一个属性的对象,这个属性就是 ‘constructor’ 且指向了这个构造器。所以一旦你覆盖了 constructor.prototype, 一定记得把 constructor.prototype.constructor 给赋值回来,否则 instance.constructor 也会出错的!

function Dog(name){
    this.name = name;
}

Dog.prototype = {
    color:'black',
    age:3
}

var dog2 = new Dog('dg2')

dog2.constructor.prototype.constructor // Object()
dog2.constructor === Dog // false, 完蛋了
dog2.constructor === Object // true, 完蛋了

//所以要记得设置回来
Dog.prototype = {
    constructor: Dog,
    color:'black',
    age:3
}

要看 constructor.prototype 这个对象它真正意义上的constructor,需要:Object.getPrototypeOf(constructor.prototype).constructor, 那自然就是 Object 无疑啦。


看文章: 对象继承 VS 类继承


dog1.constructor和dog2.constructor是Dog,上面的同学已经讲得很明白了;

关键是Dog.prototype.constructor为什么两个例子结果不同:

1.Dog.prototype.constructor默认就是Dog本身;
2.

Dog.prototype = {
...
}

覆盖了原本的默认的Dog.prototype.constructor,而你有没有重新设置constructor的值,造成constructor的丢失,所以沿原型链向上寻找constructor变成Dog.prototype.__proto__.constructor
也就是Object.prototype.constructor,最后结果变成了Object
最后给个图

推荐问题
宣传栏