这两种在JavaScript中构造对象的方法是否相同?

时间:2010-10-04 09:23:16

标签: javascript

假设:

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

是:

    var a1 = new A("A1");

完全等同于:

    var a1 = {};
    A.call(a1, "A1");
    a1.__proto__ = A.prototype;

由于

1 个答案:

答案 0 :(得分:6)

嗯,问题是__proto__是非标准的(link)并且并非所有实现都支持。 :-)除此之外,constructor属性(link)不能正确设置,你可能必须自己做。此外,我认为你最好在调用构造函数之前设置原型。所以:

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

var a1 = {};
a1.__proto__ = A.prototype;
a1.constructor = A; // <=== Added this bit
A.call(a1, "A1");   // <=== Moved this down

尽管如此,它至少在支持__proto__的实现上很接近。我不会赌它完全相同。值得阅读ECMAScript第5版规范以获取更多详细信息,特别是第11.2.2节“ new运算符”和13.2.2“ [[Construct]] ”。

某些不支持__proto__的实现可能支持第5版规范(第15.2.3.5节)定义的新Object.create函数,该函数允许您使用特定原型创建对象。在支持Object.create的实现中,创建a1的代码如下所示:

var a1 = Object.create(A.prototype);
a1.constructor = A;
A.call(a1, "A1");

滚动起来,然后:

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

if (typeof Object.create === "function") {
    a1 = Object.create(A.prototype);
}
else if ({}.__proto__) {
    a1 = {};
    a1.__proto__ = A.prototype;
}
else {
    /* Fail */
}
a1.constructor = A;
A.call(a1, "A1");

...但是这完全没有经过测试,而且,我不会指望它完全同样禁止非常仔细地阅读规范。

当然,只要有可能,如果您正在处理构造函数,我建议您以正常方式使用它。但__proto__Object.create等高级工具对于进行纯粹的原型继承(不需要构造函数)非常有用。