4

Referring to the JavaScript code snippet below, questions:

  1. Why does the object literal {item: {value: "foobar"}} behave differently when assigned to a variable (like in line 1) vs. when passed as an argument to Object.create() (like in line 5)?

  2. What is the difference between line 5 and line 8 - i.e. why is line 5 the correct way to pass the second argument to Object.create() and not line 8 (to override the item property in delegate)?

Code Snippet:

 1 var obj = {item: {value: "foobar"}};
 2 console.log(obj.item);            // [object Object]
 3 console.log(obj.item.value);      // foobar

 4 var delegate = {item: "xxx"};
 5 var obj1 = Object.create(delegate, {item: {value: "foobar"}});
 6 console.log(obj1.item);          // foobar
 7 console.log(obj1.item.value);    // undefined

 8 var obj2 = Object.create(delegate, {item: "bar"});
 9 console.log(obj2.item);          // <nothing>
RBR
  • 999
  • 3
  • 13
  • 24
  • Both Diego and Richard gave good answers to my question. How can I give credit to both of them? Or am I only allowed to give credit to one person? – RBR Aug 19 '12 at 04:53

2 Answers2

2

This happens because according to this reference: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create

Object.create receives an object with "property descriptors" as second argument, not plain key:value pairs.

See this blog post: http://ejohn.org/blog/ecmascript-5-objects-and-properties/ for a description of property descriptors.

A property descriptor is an object that describes each property, not just the property value. From your code snippet:

2 obj.item // [object Object] since item is the object {value:"foobar¨}

6 obj1.item // foobar, the descriptor says that the value 
            // of item is "foobar"

7 obj1.item.value // undefined since item="foobar", value is part of
                  // the object that describes "item" not item itself

9 obj2.item  // nothing because the descriptor that you passed 
             // for item is incomplete
Diego
  • 4,353
  • 1
  • 24
  • 22
0
  1. In line 1 your object literal is interpreted literally and instantiated as you would generally expect.

    Whereas, in line 5, your object literal is interpreted literally, but is passed into the Object.create function where the instantiated object is treated as a "properties object containing property descriptors".

  2. Because the Object.create function expects it's second parameter to follow the "Properties Object" convention, your second parameter (on line 8) is invalid (causing a Type Error in Chrome).

The following snippet may help illustrate:

var PrototypeObj = { item: 'xxx' };

var PropertiesObj = {
  propertyDescriptor1: {
    value: "prop1value",
    writable: true,
    enumerable: true,
    configurable: true
  },
  propertyDescriptor2: {
    value: "prop2value",
    writable: true,
    enumerable: true,
    configurable: true
  }
};

var Obj = Object.create(PrototypeObj, PropertiesObj);

These articles go into greater detail: Object.create, Object.defineProperty.

Community
  • 1
  • 1
rtev
  • 1,102
  • 12
  • 24