Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between Object.create(foo) and new Object(foo)?

Tags:

javascript

Why is that this code:

var foo = {one: 1, two: 2};
var bar = new Object( foo );
bar.three = 3;
bar.one = 100; 
document.write(bar.one); //100 
document.write(foo.one); //100

results in bar.one & foo.one being both 100, while

var foo = {one: 1, two: 2};
var bar = Object.create( foo );
bar.three = 3;
bar.one = 100; 
document.write(bar.one); //100
document.write(foo.one); //1

only affects bar.one..

My first intuition is that since in the first piece of code we are assigning a foo reference to bar, then it means the change will also apply to foo, while on the second code, it probably 'inherits' from foo, and therefore the change on bar's 'subclass' attribute won;t apply to its 'superclass' (prototype)..

Can somebody please confirm that my assumption is at least on the right track? Would absolutely appreciate any answers. Thanks in advance.

like image 258
Benny Tjia Avatar asked Dec 06 '22 20:12

Benny Tjia


2 Answers

The line:

var bar = new Object( foo );

In your first snippet, it doesn't do anything -you are right with your assumption-, it will simply return a reference to the same object passed to the Object constructor.

That's the behavior when you pass a native object to the Object constructor in a new expression (new Object(value)), if you pass a host object, the results are implementation dependent.

If you don't pass a value (or you explicitly pass the primitives undefined or null) a new object that inherits from Object.prototype will be created.

Otherwise, if you pass any of the remaining primitives (as a Number, String or a Boolean value), a primitive wrapper object will be created (basically "primitive-to-object" type conversion), for example.

var s = new String("foo"); // a string object wrapper
typeof s;     // "object"
s.valueOf();  // "foo"

See this question about primitives and objects: How is a Javascript string not an object?

In your second snippet, the line:

var bar = Object.create( foo );

Creates a new object, that inherits from foo, and since it's a different object, when you assign the properties:

bar.three = 3;
bar.one = 100;

Those will be created physically on that separated instance, as you can see, the bar.one property shadows the value contained in foo.

The object referenced by bar, in fact will contain two own properties (one and three, but since it inherits from foo, the property named two is resolvable through the prototype chain, for example:

bar.hasOwnProperty('one'); // true, the property is "own"
bar.hasOwnProperty('two'); // false, the property is "inherited" from foo
bar.two; // 2, is accessible

Basically, the prototype chain of bar looks like this:

                                                      -----------------
                                           ========> | Object.prototype| ==> null
                                           |          -----------------
|-------------|     [[Prototype]]     |---------|
| one:   100  | ====================> |  one: 1 | (shadowed)
| three: 3    |                       |  two: 2 |
|-------------|                       |---------|

(== line denotes the prototype chain)
like image 153
Christian C. Salvadó Avatar answered Dec 10 '22 11:12

Christian C. Salvadó


new Object and Object.create do completely different things, despite their similar sounding names.

new Object(), with no argument, is equivalent to an empty object literal {}, which you should always use instead. With an argument, new Object(obj) simply returns the argument.

Object.create(obj) helps untangle JavaScript's messed up prototypal inheritance. Reading this article by Douglas Crockford will help with that. Basically, it creates a new object that inherits from obj. So if you have

var obj1 = {x: 1}, obj2 = Object.create(obj1);

obj1.x; // 1
obj2.x; // 1

obj2.x = 42;
obj1.x; // 1

obj1.x = 10;
obj2.x; // 10, since obj2 inherits from obj1, changing obj1's properties
        // changes obj2, but not the other way around.
like image 41
Peter C Avatar answered Dec 10 '22 13:12

Peter C