I recently stumbled upon the Object.create()
method in JavaScript, and am trying to deduce how it is different from creating a new instance of an object with new SomeFunction()
, and when you would want to use one over the other.
Consider the following example:
var test = {
val: 1,
func: function() {
return this.val;
}
};
var testA = Object.create(test);
testA.val = 2;
console.log(test.func()); // 1
console.log(testA.func()); // 2
console.log('other test');
var otherTest = function() {
this.val = 1;
this.func = function() {
return this.val;
};
};
var otherTestA = new otherTest();
var otherTestB = new otherTest();
otherTestB.val = 2;
console.log(otherTestA.val); // 1
console.log(otherTestB.val); // 2
console.log(otherTestA.func()); // 1
console.log(otherTestB.func()); // 2
Notice that the same behaviour is observed in both cases. It seems to me that the primary differences between these two scenarios are:
- The object used in
Object.create()
actually forms the prototype of the new object, whereas in thenew Function()
from the declared properties/functions do not form the prototype. - You cannot create closures with the
Object.create()
syntax as you would with the functional syntax. This is logical given the lexical (vs block) type scope of JavaScript.
Are the above statements correct? And am I missing something? When would you use one over the other?
EDIT: link to jsfiddle version of above code sample: http://jsfiddle.net/rZfYL/
Very simply said,
new X
isObject.create(X.prototype)
with additionally running theconstructor
function. (And giving theconstructor
the chance toreturn
the actual object that should be the result of the expression instead ofthis
.)That’s it. :)
The rest of the answers are just confusing, because apparently nobody else reads the definition of
new
either. ;)Let me try to explain (more on Blog) :
Car
constructorvar Car = function(){}
, this is how things are internally: We have one{prototype}
hidden link toFunction.prototype
which is not accessible and oneprototype
link toCar.prototype
which is accessible and has an actualconstructor
ofCar
. Both Function.prototype and Car.prototype have hidden links toObject.prototype
.When we want to create two equivalent objects by using the
new
operator andcreate
method then we have to do it like this:Honda = new Car();
andMaruti = Object.create(Car.prototype)
. What is happening?Honda = new Car();
— When you create an object like this then hidden{prototype}
property is pointed toCar.prototype
. So here, the{prototype}
of the Honda object will always beCar.prototype
— we don't have any option to change the{prototype}
property of the object. What if I want to change the prototype of our newly created object?Maruti = Object.create(Car.prototype)
— When you create an object like this you have an extra option to choose your object's{prototype}
property. If you want Car.prototype as the{prototype}
then pass it as a parameter in the function. If you don't want any{prototype}
for your object then you can passnull
like this:Maruti = Object.create(null)
.Conclusion — By using the method
Object.create
you have the freedom to choose your object{prototype}
property. Innew Car();
, you don't have that freedom.Preferred way in OO JavaScript :
Suppose we have two objects
a
andb
.Now, suppose
a
has some methods whichb
also wants to access. For that, we require object inheritance (a
should be the prototype ofb
only if we want access to those methods). If we check the prototypes ofa
andb
then we will find out that they share the prototypeObject.prototype
.Problem — we want object
a
as the prototype ofb
, but here we created objectb
with the prototypeObject.prototype
. Solution — ECMAScript 5 introducedObject.create()
, to achieve such inheritance easily. If we create objectb
like this:then,
So, if you are doing object oriented scripting then
Object.create()
is very useful for inheritance.Accordingly to this answer and to this video
new
keyword does next things:Creates new object.
Links new object to constructor function (
prototype
).Makes
this
variable point to the new object.Executes constructor function using the new object and implicit perform
return this
;Assigns constructor function name to new object's property
constructor
.Object.create
performs only1st
and2nd
steps!!!Here are the steps that happen internally for both calls:
(Hint: the only difference is in step 3)
new Test()
:new Object()
objobj.__proto__
toTest.prototype
return Test.call(obj) || obj; // normally obj is returned but constructors in JS can return a value
Object.create( Test.prototype )
new Object()
objobj.__proto__
toTest.prototype
return obj;
So basically
Object.create
doesn't execute the constructor.This:
and
are quite similar. One important difference is that
new Foo
actually runs constructor code, whereasObject.create
will not execute code such asNote that if you use the two-parameter version of
Object.create()
then you can do much more powerful things.Internally
Object.create
does this:The syntax just takes away the illusion that JavaScript uses Classical Inheritance.