0

look at this code :

        var Test = {
        options: {
            name: 'foo'
        },
        name: 'foo',
        init: function (name) {
            this.name = name;
            this.options.name = name;
        }
    };

    var dict = {};

    for (var i = 0; i < 3; i++) {
        var obj = Object.create(Test);
        obj.init(i);
        dict[i] = obj;
    }

i don't understand why all the properties in dict[X].options.name in the object dict has the value same value(2) and the propertiesin dict[X].name has different value ?

3
  • I believe you need to call Object.create(Test.prototype). Commented Sep 14, 2011 at 12:16
  • @Tejs: Test.prototype is an empty object. Commented Sep 14, 2011 at 12:23
  • @Tejs. No, thats how Object.create works. The .prototype is a hack for the new syntax. Commented Sep 14, 2011 at 12:23

3 Answers 3

1

It looks like something to do with passing values by reference.

The object Test contains a reference to another object in property options. When a new instance of Test is created the new instance get a reference to the existing options instance instead of getting a new copy of the object.

A rough image will be something like enter image description here

You can check it by adding the following statement at the bottom of your code

alert(Test.options== dict[0].options);
Sign up to request clarification or add additional context in comments.

Comments

1

The documentation is clear:

Creates a new object with the specified prototype object and properties.

So Test will be the prototype of the new object. All instances reference the same prototype and as options is an object, they also share a reference to this one.

The relation looks like this:

+------------+      +---------+       +--------+
| Instance 1 |----->| Test    |       | Object |
+------------+      |         |       |        |
                    | options-|------>| name   | 
                    | name    |       +--------+
                    +---------+
                         ^ 
+------------+           |
| Instance 2 |-----------+
+------------+      

Now, as options is an object, if you assign a new property to it, like

instance1.object.name2 = 'bar';

you are actually accessing Test.options. The result will be:

+------------+      +---------+       +--------+
| Instance 1 |----->| Test    |       | Object |
+------------+      |         |       |        |
                    | options-|------>| name   | 
                    | name    |       | name2  |
                    +---------+       +--------+
                         ^
+------------+           |
| Instance 2 |-----------+
+------------+ 

But when you assign a new value to name, a new property name will be created at that instance. So when you do:

instance1.name = 'bar';

the result will be

+------------+      +---------+       +--------+
| Instance 1 |----->| Test    |       | Object |
|            |      |         |       |        |
| name       |      | options-+------>| name   | 
+------------+      | name    |       +--------+
                    +---------+
                         ^
+------------+           |
| Instance 2 |-----------+
+------------+      

The same would happen if, instead of just accessing or assigning a property of/to options, you assigned a new value to it:

instance1.options = {name: 'another name'};

results in:

           +--------+
           | Object |
           |        |
           | name   |
           +--------+
                ^
+------------+  |   +---------+       +--------+
| Instance 1 |--+-->| Test    |       | Object |
|            |  |   |         |       |        |
| options----+--+   | options-|------>| name   | 
+------------+      | name    |       +--------+
                    +---------+
                         ^
+------------+           |
| Instance 2 |-----------+
+------------+

Because of how property look up works, instance1.options will return the value of the closest (nearest) options property in the prototype chain. Once we set name or options at the instance, it will return those values and not the ones of the prototype (Test).

1 Comment

I think that doesn't answer the question why name varies for all instances and options.name doesn't. But... may be I am mistaken. Will provide my answer anyway.
0

I think you are a bit confused here.

options: {
    name: 'foo'
},
name: 'foo'

as you defined them, and then used in your Object.create() statement, belong to the prototype and as such are the same for all objects with the same prototype.

The reason you see name attribute changed is because you created it on each instance (essentially overriding that defined in the prototype) by calling:

this.name = name;

Something that doesn't happen for the object property because you never assigned it directly. Instead it takes the last assigned value (which would be 2 in your example).

Had you written:

this.options = {};
this.options.name = name;

in your init function - options.name would be overridden on each instance and be just like you wanted it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.