4

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.

Benny Tjia
  • 4,853
  • 10
  • 39
  • 48

2 Answers2

13

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)
Community
  • 1
  • 1
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • thanks for the response..so does it mean that my assumption is correct? that var bar = new Object(foo) is pretty much the same as var bar = foo therefore bar now stores the reference of foo? and also, what is a primitive wrapper? – Benny Tjia Aug 07 '11 at 02:14
  • @BennyTija: Yeah, that means your assumption is correct. A primitive wrapper is an object that wraps a primitive value, like Java's Integer class. There isn't much use for them, although if you're calling a lot of methods on a primitive it can help to wrap it for performance reasons. – Peter C Aug 07 '11 at 02:21
  • @BennyTija, as @alpha123 says, your assumption is right, about primitive wrappers, Javascript has five primitive types, which are String, Number, Boolean, Null and Undefined, values of this types are *primitive*, they are not objects, basically primitive wrappers are objects that store a primitive internally, they are not so useful on the language because you can still access properties on primitive values, e.g. `"foo".charAt(0); // "f"`. They are actually a heritage from Java... See my answer on the question I [linked](http://stackoverflow.com/questions/3907613/). – Christian C. Salvadó Aug 07 '11 at 02:32
2

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.
Peter C
  • 6,219
  • 1
  • 25
  • 37