Javascript 原型和构造函数对象属性

Javascript 原型和构造函数对象属性,javascript,prototype,constructor,Javascript,Prototype,Constructor,我已经: 现在当我这样做的时候: 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) 但构造函数已被禁用。。。为什么? Obj1已成为Obj2原型 有人能详细

我已经:

现在当我这样做的时候:

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) 
但构造函数已被禁用。。。为什么? Obj1已成为Obj2原型

有人能详细解释一下原型链和构造函数属性吗


感谢

构造函数
是原型对象的常规属性(设置了
DontEnum
标志,因此它不会显示在
for..in
循环中)。如果替换prototype对象,则
构造函数
属性也将被替换-有关更多详细信息,请参阅

您可以通过手动设置
Obj2.prototype.constructor=Obj2
来解决此问题,但这样就不会设置
DontEnum
标志

由于这些问题,依赖
构造函数进行类型检查不是一个好主意:改用
instanceof
isPrototypeOf()


Andrey Fedorov提出了一个问题,为什么
new
不将
构造函数
属性分配给实例对象。我想原因如下:

从同一构造函数创建的所有对象共享构造函数属性,共享属性驻留在原型中

真正的问题是JavaScript没有对继承层次结构的内置支持。围绕这个问题有几种方法(您的方法就是其中之一),另一种“本着JavaScript的精神”的方法是:

function Obj1(param) {
    this.test1 = param || 1;
}
函数addOwnProperties(obj/*,…*/){
对于(变量i=1;i
这也使得多重继承变得微不足道。

请查看“继承”页面。原型中的所有内容都被继承,包括
构造函数
属性。因此,我们必须自己打破它:

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() {};

构造函数属性和其他属性一样,是Obj1原型(属性)上的属性。如果您愿意,这可能会有帮助:

Obj2.prototype = new Obj1(42);
Obj2.prototype.constructor = Obj2;
啊哈!所以obj没有构造函数,JS从Obj1.Prototype.constructor一直到[[Prototype]]链上去获取它


我不知道为什么在使用'new'时,构造函数属性不只是在对象上设置的。可能有原因,也可能只是疏忽。无论哪种方式,我都倾向于避免使用它。

简短版本:“constructor”不符合您的想法,并且不兼容跨浏览器。永远不要使用它

长版本:

通常情况下:您会感到困惑,因为(a)基于类和基于原型的OO之间的阻抗不匹配,以及(b)JavaScript对基于原型的OO的解释非常糟糕

如果在原型实现中找到一个您喜欢的类并坚持下去,您可能会更高兴。许多图书馆都有一个。下面是我使用的任意一个:

>>> 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()
下面是一个如何使用它的示例:

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();

constructor
是由同一个构造函数创建的所有实例对象之间共享的属性,因此,将其放在原型中是正确的;只是JS没有内置的对(深层)继承层次结构的支持——我将对我的答案进行解释。。。
// 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);