Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are these two ways of constructing an object in JavaScript equivalent?

Tags:

javascript

Given:

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

is:

    var a1 = new A("A1");

exactly equivalent to:

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

?

Thanks

like image 568
zod Avatar asked Oct 04 '10 09:10

zod


1 Answers

Well, there's the issue that __proto__ is non-standard (link) and not supported by all implementations. :-) Other than that, the constructor property (link) wouldn't be set correctly, you'd probably have to do that yourself. Also, I think you'd be best off setting the prototype before calling the constructor function. So:

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

It's close, though, at least on implementations that support __proto__. I wouldn't bet on it being exactly the same. Worth having a read of the ECMAScript 5th edition spec for more details, particular Sections 11.2.2 "The new operator" and 13.2.2 "[[Construct]]".

Some implementations that don't support __proto__ may support the new Object.create function defined by the 5th edition spec (Section 15.2.3.5), which allows you to create an object with a specific prototype. In implementations that support Object.create, the code creating a1 would look like this:

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

Rolling it up, then:

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

...but that's completely untested and, again, I wouldn't count on it being exactly the same barring a very close read of the spec indeed.

Whenever possible, of course, if you're dealing with a constructor function, I'd recommend using it in the normal way. Advanced tools like __proto__ and Object.create are useful for doing pure prototypical inheritance (no constructor function required), though.

like image 177
T.J. Crowder Avatar answered Sep 28 '22 00:09

T.J. Crowder