我目前正在阅读Stoyan Stefanov的书“面向对象的JavaScript”,我偶然发现了一个有趣的问题。这是代码:
var shape = {
type: 'shape',
getType: function() {
return this.type;
}
};
function Triangle(a, b, c) {
this.a = a;
this.b = b;
this.c = c;
this.type = 'triangle';
}
Triangle.prototype = shape; // changing the prototype object
Triangle.prototype.getPerimeter = function() {
return this.a + this.b + this.c;
}
var t = new Triangle(1, 2, 3);
t.constructor; // logs Object() instead of Triangle(a, b, c)
正如您所看到的,这是一个构造函数的简单示例,其中包含原型对象的一些属性。但是对象t的构造函数属性指向Object()对象而不是Triangle(a,b,c),因为它应该具有。如果我用原型更改评论该行,一切正常。我的问题是什么? (重读面向对象的Javascript和JavaScript模式中的整个原型章节,找不到答案)。 附:抱歉我的英语不好,试着去练习。 :)
答案 0 :(得分:6)
我将分两部分解释您的代码。首先,实际上constructor
属性是什么?其次,为什么不在代码中返回Objects
?
constructor
属性和Stoyan的错误:在Stoyan Stefanov的书中,p150,他说:
prototype是一个定义函数后立即创建的属性。 其初始值为空对象。
错误。根据{{3}}第9.2节
prototype属性的初始值是具有单个属性的对象。 此属性名为constructor ,并引用与原型关联的构造函数。
您可以使用Triangle.prototype.constructor
进行测试。它已在定义函数时设置。
结论1 :constructor
实际上是Constructor.prototype
的属性。在您的情况下,它是Triangle.prototype.constructor
。
Triangle
的所有实例都可以通过原型链访问此属性。 但是这些对象本身没有constructor
属性。以下代码证明了这一点:
function Triangle(a, b, c) {
this.a = a;
this.b = b;
this.c = c;
this.type = 'triangle';
}
var t = new Triangle(1, 2, 3);
t.hasOwnProperty('constructor');
>>false
t.__proto__.hasOwnProperty('constructor');
>>true
结论2 :当您访问实例的constructor
属性时,您可以从原型链中获取它们。
您将Triangle.prototype
设置为shape
不包含原始constructor
属性。
因此,这次,当您查询t.constructor
时,它将在以下过程中解决它:
constructor
t.__proto__
,Triangle.prototype
。您已将其设置为shape
,但不包含constructor
属性。t.__proto__.__proto__
。它是Triangle.prototype.__proto__
,它被解析为Object.prototype
。 Object.prototype
具有constructor
属性,它引用Object
。答案 1 :(得分:3)
奇怪的是,“构造函数”属性不引用该对象的构造函数。相反,它指的是对象原型的构造函数。
Here是Mozilla的相关文档页面。
答案 2 :(得分:1)
shape
是一个对象,所以这样做:
Triangle.prototype = shape;
您将Triangle
构造函数更改为Object
答案 3 :(得分:1)
在这里,您基本上使用基于本机/类的继承。
在Javascript中,(根据我的理解)当您使用new
关键字时,您可以使用构造函数和附加的原型对象创建一个函数对象。
执行此操作时:
Triangle.prototype = shape;
您重写构造函数方法。您可以使用控制台在将形状分配到Triangle.prototype
之前和之后观察对象。
当你这样做时:
t.constructor;
您无法查看您希望看到的内容,因为对构造函数方法的调用会在原型链中找到构造函数方法。
答案 4 :(得分:0)
shape不是构造函数,而是对象。它的构造函数是Object构造函数。
如果shape是构造函数,则可以设置
Triangle.prototype = new shape;
和Triangle.prototype.constructor = Triangle,以覆盖刚刚设置的shape.prototype.constructor。
答案 5 :(得分:-1)
var shape = {
type: 'shape',
getType: function () {
return this.type
}
}
function Triangle(a, b, c) {
this.type = 'triangle'
this.a = a;
this.b = b;
this.c = c;
}
Triangle.prototype = shape;
Triangle.prototype.constructor = Triangle;
Triangle.prototype.getPerimeter = function () {
return this.a + this.b + this.c
}
var t = new Triangle(1, 2, 3)
console.log(t.constructor === Triangle) // true
console.log(shape.isPrototypeOf(t)) // true
console.log(t.getPerimeter()) // 6
console.log(t.getType()) // triangle