我已经:
function Obj1(param)
{
this.test1 = param || 1;
}
function Obj2(param, par)
{
this.test2 = param;
}
现在我做的时候:
Obj2.prototype = new Obj1(44);
var obj = new Obj2(55);
alert(obj.constructor)
我有:
function Obj1(param) {
this.test1 = param || 1;
}
但是构造函数已经是Obj2 ......为什么呢? Obj1已成为Obj2原型......
有人可以详细解释我的原型链和构造函数属性
由于
答案 0 :(得分:25)
constructor
是原型对象的常规属性(设置了DontEnum
标志,因此它不会显示在for..in
循环中)。如果替换原型对象,constructor
属性也将被替换 - 有关详细信息,请参阅this explanation。
您可以通过手动设置Obj2.prototype.constructor = Obj2
来解决此问题,但这样就不会设置DontEnum
标记。
由于存在这些问题,依靠constructor
进行类型检查并不是一个好主意:请改用instanceof
或isPrototypeOf()
。
Andrey Fedorov提出了为什么new
没有将constructor
属性分配给实例对象的问题。我猜其原因如下:
从同一构造函数创建的所有对象共享构造函数属性,共享属性驻留在原型中。
真正的问题是JavaScript没有内置的继承层次结构支持。围绕这个问题有几种方法(你的是其中之一),另外一种方法是JavaScript中的“精神”如下:
function addOwnProperties(obj /*, ...*/) {
for(var i = 1; i < arguments.length; ++i) {
var current = arguments[i];
for(var prop in current) {
if(current.hasOwnProperty(prop))
obj[prop] = current[prop];
}
}
}
function Obj1(arg1) {
this.prop1 = arg1 || 1;
}
Obj1.prototype.method1 = function() {};
function Obj2(arg1, arg2) {
Obj1.call(this, arg1);
this.test2 = arg2 || 2;
}
addOwnProperties(Obj2.prototype, Obj1.prototype);
Obj2.prototype.method2 = function() {};
这也使多重继承变得微不足道。
答案 1 :(得分:9)
查看Tom Trenka's OOP woth ECMAscript,“继承”页面。原型中的 Everything 是继承的,包括constructor
属性。因此,我们必须自己解开它:
Obj2.prototype = new Obj1(42);
Obj2.prototype.constructor = Obj2;
答案 2 :(得分:3)
简短版本:'构造函数'不符合您的想法,并且不兼容跨浏览器。永远不要使用它。
长版:Convention for prototype inheritance in JavaScript
一般来说:由于(a)基于类和基于原型的OO之间的阻抗不匹配,以及(b)JavaScript对基于原型的OO特别差的解释的陌生感,你会感到困惑。
如果您发现自己喜欢的一个原型类实现并坚持下去,那么您可能会更开心。许多图书馆都有一个。这是我使用的任意一个:
Function.prototype.subclass= function() {
var c= new Function(
'if (!(this instanceof arguments.callee)) throw(\'Constructor called without "new"\'); '+
'if (arguments[0]!==Function.prototype.subclass.FLAG && this._init) this._init.apply(this, arguments); '
);
if (this!==Object)
c.prototype= new this(Function.prototype.subclass.FLAG);
return c;
}
Function.prototype.subclass.FLAG= new Object();
这是一个如何使用它的例子:
// make a new class
var Employee= Object.subclass();
// add members to it
Employee.prototype._LEGS= 2;
Employee.prototype.getLegs= function() {
return this._LEGS;
};
// optional initialiser, takes arguments from constructor
Employee.prototype._init= function(name) {
this.name= name;
};
// make a subclass
Manager= Employee.subclass();
// extend subclass method
Manager.prototype._init= function(name, importance) {
// call base class's method
Employee.prototype._init.call(this, name);
this.importance= importance;
}
// all managers are well-known to have three legs
Manager.prototype._LEGS= 3;
// create one
var jake= new Manager('Jake the Peg', 100);
答案 3 :(得分:1)
嗯,构造函数属性是Obj1的prototype(property)上的任何其他属性。如果您understand how prototypes work,这可能有所帮助:
>>> obj.hasOwnProperty("constructor")
false
// obj's [[Prototype]] is Obj2.prototype
>>> Obj2.prototype.hasOwnProperty("constructor")
false
// Obj2.prototype's [[Prototype]] is Obj1.prototype
>>> Obj1.prototype.hasOwnProperty("constructor")
true
// Oh?
>>> Obj1.prototype.constructor
Obj1()
啊哈!所以obj没有构造函数,JS去了[[Prototype]]链,从Obj1.prototype.constructor一直到
我不确定为什么在使用`new'时,构造函数属性不只是在对象上设置。可能有原因,或者可能只是疏忽。无论哪种方式,我都倾向于避免它。