Understanding the difference between Object.create() and new SomeFunction()
Solution 1
The object used in Object.create actually forms the prototype of the new object, where as in the new Function() form the declared properties/functions do not form the prototype.
Yes, Object.create
builds an object that inherits directly from the one passed as its first argument.
With constructor functions, the newly created object inherits from the constructor's prototype, e.g.:
var o = new SomeConstructor();
In the above example, o
inherits directly from SomeConstructor.prototype
.
There's a difference here, with Object.create
you can create an object that doesn't inherit from anything, Object.create(null);
, on the other hand, if you set SomeConstructor.prototype = null;
the newly created object will inherit from Object.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.
Well, you can create closures, e.g. using property descriptors argument:
var o = Object.create({inherited: 1}, {
foo: {
get: (function () { // a closure
var closured = 'foo';
return function () {
return closured+'bar';
};
})()
}
});
o.foo; // "foobar"
Note that I'm talking about the ECMAScript 5th Edition Object.create
method, not the Crockford's shim.
The method is starting to be natively implemented on latest browsers, check this compatibility table.
Solution 2
Very simply said, new X
is Object.create(X.prototype)
with additionally running the constructor
function. (And giving the constructor
the chance to return
the actual object that should be the result of the expression instead of this
.)
That’s it. :)
The rest of the answers are just confusing, because apparently nobody else reads the definition of new either. ;)
Solution 3
Here are the steps that happen internally for both calls:
(Hint: the only difference is in step 3)
new Test()
:
- create
new Object()
obj - set
obj.__proto__
toTest.prototype
return Test.call(obj) || obj; // normally obj is returned but constructors in JS can return a value
Object.create( Test.prototype )
- create
new Object()
obj - set
obj.__proto__
toTest.prototype
return obj;
So basically Object.create
doesn't execute the constructor.
Solution 4
Let me try to explain (more on Blog) :
- When you write
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. In new Car();
, you don't have that freedom.
Preferred way in OO JavaScript :
Suppose we have two objects a
and b
.
var a = new Object();
var b = new Object();
Now, suppose a
has some methods which b
also wants to access. For that, we require object inheritance (a
should be the prototype of b
only if we want access to those methods). If we check the prototypes of a
and b
then we will find out that they share the prototype Object.prototype
.
Object.prototype.isPrototypeOf(b); //true
a.isPrototypeOf(b); //false (the problem comes into the picture here).
Problem — we want object a
as the prototype of b
, but here we created object b
with the prototype Object.prototype
.
Solution — ECMAScript 5 introduced Object.create()
, to achieve such inheritance easily. If we create object b
like this:
var b = Object.create(a);
then,
a.isPrototypeOf(b);// true (problem solved, you included object a in the prototype chain of object b.)
So, if you are doing object oriented scripting then Object.create()
is very useful for inheritance.
Solution 5
This:
var foo = new Foo();
and
var foo = Object.create(Foo.prototype);
are quite similar. One important difference is that new Foo
actually runs constructor code, whereas Object.create
will not execute code such as
function Foo() {
alert("This constructor does not run with Object.create");
}
Note that if you use the two-parameter version of Object.create()
then you can do much more powerful things.
Matt
C#, ASP.NET MVC, JavaScript, Ruby, and Ruby on Rails developer.
Updated on July 08, 2022Comments
-
Matt almost 2 years
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 withnew 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/
- The object used in
-
Christian C. Salvadó over 13 yearsThe ECMAScript 5
Object.create
method, does a lot more than that, you can define properties by property descriptors and you can create an object that doesn't inherit from anything (Object.create(null);
), this type of shims should be avoided because you can't really emulate that behavior on ES3. More info -
Matt over 13 years@CMS 2 questions. 1) Does the scope chain on Object.create(null) still terminate at the global scope (such as 'window' in a browser), or does it terminate on itself? 2) It is still not clear to me why Object.create was introduced (e.g. what feature was missing that this addressed?) and why one would use it instead of new Function();
-
Christian C. Salvadó over 13 years@Matt, 1) the scope chain is not really a related concept here, scope chain is related to identifier resolution, e.g.: how
foo;
is resolved in the current lexical environment. 2) To provide an easy way to implement inheritance, it's a really powerful construct. IMO I would use it because it's really simple and lightweight, but for production code, we still need to wait some time until ES5 is supported widely. About missing features, the fact of creating a "pristine" object,Object.create(null);
was missing, it's really useful to implement reliable hash-table-like objects... -
Anshul almost 10 years@CMS Thanks. So simply when you create a object by using 'Object.create',you get the ability to select the object that should be its prototype.
-
user949300 almost 10 years@CMS O.K., so
Object.create(null)
means you don't have to usehasOwnProperty()
crap when iterating cause it inherits none??? I like that - thanks. Of course, everybody is still going to dohasOwnProperty
since not everybody will useObject.create(null)
so I'm not sure it's a real benefit... So far I have found the other "benefits" ofObject.create()
completely unconvincing. -
user949300 almost 10 years+1 Simplicity and clarity! (Though the Object.create(null) seems a nice option - maybe should mention that).
-
Ricky Boyce over 8 yearsGreat explanation. Might I add, using
Object.create
in its simplest form like this allows you to omit constructor functions from your code while taking advantage of prototype inheritance. -
Praveen about 8 yearsSo, it is somewhat similar to object creation without constructor invocation? We will enjoy all the benefits of the class. The obj instanceof Class will also be true. But we are not invoking the Class function via new.
-
Bill about 8 yearskeep it simple that's the way to go
-
Qwertie about 8 yearsThat just leaves the question of "wait, so functions have prototypes too? What's the relationship between those and object prototypes?"
-
Evi1M4chine almost 8 years@Qwertie: In JS, everything is an object. :) They copied that from Java, who copied it from SmallTalk, who went all the way to the end with it. It’s a nice case of “emergence”, making life easier in general.
-
Qwertie almost 8 years@Evi1M4chine actually in Java, functions are not objects (and neither are primitives, for that matter)... and objects don't have prototypes, so the comparison seems un-fitting. The fact that JS works differently than other popular OO languages is a major source of confusion (and it doesn't help that browsers don't provide an easy way to visualize the network of objects including functions and prototypes). P.S. I found this link helpful : davidwalsh.name/javascript-objects-deconstruction
-
Sagar Karira over 7 years@Anshul You said that
a.isPrototypeOf(b);
will returnfalse
which is right, because both Objects are different and pointing to different memory. The correct way to do this with thenew
operator is here. - jsfiddle.net/167onunp . -
Evi1M4chine over 7 years@Qwertie: I didn’t say that Java fully did follow that philosophy. They had the philosophy. They just half-assed it. :) But SmallTalk certainly followed it. … And OOP does not equal class-based OOP.. JS is prototype-based OOP, but they all have OOP in common. In fact JS’s OOP philosophy is much cleaner, more elegant and more universal than the class-based approach. They just failed to implement it nicely too. (JavaScript 2 was supposed to solve all that, and would have been quite nice. WebAssembly made all of it moot. :)
-
Amnestic over 7 yearsWhy wouldn't you just set the prototype property of b to a, instead of doing this?
-
Admin over 7 years@Ray so using object.create we font have the properties of function mentioned in constructor function?
-
Kamafeather almost 7 years@sortednoun as long as the properties are private and not specified on the prototype, yes, they won't be inherited and you won't have them in the new object (and, I would add, you can expect to get eventual prototyped properties from the parent, just when the parent constructor has been execute at least once).
-
cn007b almost 7 yearsAgree with @CMS but in general, it is simple polyfill for
Object.create
. -
mansoor.khan almost 7 yearsLiked the article on your blog too. Helped me understand the concept much better. Thank you.
-
HalfWebDev almost 7 yearsThe conclusion says it all.
-
yyny over 6 yearsNote that on all modern JavaScript implementations the 'hidden'
[[Prototype]]
can be accessed as__proto__
(non-standard) and with theObject.getPrototypeOf
function. -
Anandaraja_Srinivasan over 4 yearsNice Summary. Thanks. It helped me today !!
-
SparK about 4 yearsAs with most constructor functions the methods are defined within the returned object,
new
basically has all functions duplicated, whileObject.create
doesn't. -
Soner from The Ottoman Empire almost 4 years
===
operator is intricate here since I don't understand how it works on your second explanation.==
would be hunky-dory but===
. -
Bergi over 3 yearsDon't use
new Object
, use an object literal. -
Bergi over 3 yearsDon't use
.bind(x)(...args)
, just.call(x, ...args)
. -
redOctober13 over 2 yearsThis was the important difference to me. If my prototype has props with values and I use
Object.create()
and then try to say get the value of those props on the object, I'll getundefined
whereas sincenew()
runs the constructor, I can immediately query prop values. -
Evi1M4chine about 2 years@Dmitry: Because some objects want to initialize external resources in their constructors (and destroy them in their destructors). Like file handles, sockets, network connections, memory areas, temporary files, GPU state, etc. E.g. a File object in a hypothetical language would be created by opening a file and getting the handle during its construction. A good garbage collector automatically calls the destructor and is smart about it by using the concept of volatile resources too, to not exhaust them.
-
Evi1M4chine about 2 years@Dmitry: And returning an other object is very useful for the design pattern of singletons, for example. There, there is only ever one instance, and on creation, it does not return the new object, but the already existing one, and discards that newly created instance right away.
-
Dmytro about 2 years@Evi1M4chine I have deleted my comment as I cannot remember the mental state I was in writing it*(2018)
-
kungfooman about 2 years@Bergi
.apply(x, args)
;-)