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/
Object creation variants.
Variant 1 : 'new Object()' -> Object constructor without arguments.
Variant 2 : 'new Object(person)' -> Object constructor with argument.
Variant 3.1 : 'Object.create(person)'. Use Object.create with simple object 'person'. 'Object.create(person)' will create(and return) new empty object and add property '__proto__' to the same new empty object. This property '__proto__' will point to the object 'person'.
Variant 3.2 : 'Object.create(Object.prototype)'. Use Object.create with built-in object -> 'Object.prototype'. 'Object.create(Object.prototype)' will create(and return) new empty object and add property '__proto__' to the same new empty object. This property '__proto__' will point to the object 'Object.prototype'.
Variant 4 : 'new SomeFunction()'
The difference is the so-called "pseudoclassical vs. prototypal inheritance". The suggestion is to use only one type in your code, not mixing the two.
In pseudoclassical inheritance (with "new" operator), imagine that you first define a pseudo-class, and then create objects from that class. For example, define a pseudo-class "Person", and then create "Alice" and "Bob" from "Person".
In prototypal inheritance (using Object.create), you directly create a specific person "Alice", and then create another person "Bob" using "Alice" as a prototype. There is no "class" here; all are objects.
Internally, JavaScript uses "prototypal inheritance"; the "pseudoclassical" way is just some sugar.
See this link for a comparison of the two ways.
Summary:
1) with
new
keyword there are two things to note;a) function is used as a constructor
b)
function.prototype
object is passed to the__proto__
property ... or where__proto__
is not supported, it is the second place where the new object looks to find properties2) with
Object.create(obj.prototype)
you are constructing an object (obj.prototype
) and passing it to the intended object ..with the difference that now new object's__proto__
is also pointing to obj.prototype (please ref ans by xj9 for that)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.:
In the above example,
o
inherits directly fromSomeConstructor.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 setSomeConstructor.prototype = null;
the newly created object will inherit fromObject.prototype
.Well, you can create closures, e.g. using property descriptors argument:
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.