0

As the title says, I have hit a conceptual snag in understanding how Object.create() works.

It was my impression that, after using this method, the resulting object would inherit the values of the object passed as argument to Object.create(). In the simple example below, I can create an object and access its inherited values, I can even correctly get the prototype of the new object, however the Object.keys() array is empty!

let obj = Object.create({x: 1, y: 2});
console.log("Keys of obj:");
Object.keys(obj).forEach(function (key) {
  console.log(key + ' - ' + obj[key]);
});
console.log("Prototype of obj:");
console.log(Object.getPrototypeOf(obj));
console.log("obj.x = " + obj.x);

Console result:

acg@acg:~/dev/$ node test.js 
Keys of obj:
Prototype of obj:
{ x: 1, y: 2 }
obj.x = 1

(Just to eliminate any confusion: I get the same results when substituting Object.getOwnPropertyNames() for Object.keys(), by the way).

Am I misunderstanding something? Why is the keys array empty?

EDIT: Am I right in assuming that Object.keys() and Object.getOwnPropertyNames() only give me the properties directly available on an object, i.e. not inherited? Then, I think my question is: is there a function that gives me an object's properties? (inherited or otherwise)

EDIT2: Nope -- got to traverse the prototype chain manually, as shown here: Is it possible to get the non-enumerable inherited property names of an object?

EDIT3: According to answer from Pol Martin below, one can use a for..in construct to loop over all properties (including those inherited). Also see https://stackoverflow.com/a/208439/7705625

Community
  • 1
  • 1
ACEG
  • 1,981
  • 6
  • 33
  • 61
  • [`Object.keys`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys) returns _An array of strings that represent all the enumerable properties of the given object._ And inherited properties are non-enumerable. See [Enumerability and ownership of properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties) check the table at the bottom. – Tushar Mar 14 '17 at 10:40
  • @Tushar Yes, and my question is: why is that array and also getOwnPropertyNames empty, if I can access obj.x? – ACEG Mar 14 '17 at 10:41
  • Short Version : When you do obj.x -> First it tries to find x in direct properties, if not available it goes to find it in the parent/proto. So the result it is returning in your case is from the parent. – inQstvJS Mar 14 '17 at 10:42
  • @inQstvJS That's clear. But does keys() or getOwnPropertyNames() do the same? I assume not (see my edited post). I need a way to find all properties on an object, whether inherited or not. – ACEG Mar 14 '17 at 10:48

1 Answers1

1

Object.create has two arguments. The first one is the prototype of the created object, and a second optional parameter is an object of property descriptors.

Object.create(proto[, propertiesObject])

If you create the object passing the properties object as the first argument,

let obj = Object.create({x: 1, y: 2});

this one will become the prototype of your new object. As Object.keys() returns an array of only its own enumerable properties, the ones you passed when constructing it won't be listed.

To create the object the way you intended, yo can use Object.assign:

let obj = Object.assign({}, {x: 1, y: 2});
  • Thanks -- I had already suspected as much. Is there a way to get all properties defined on an object, whether they are inherited or otherwise? Or would I have to build my own traversing of the prototype chain for this? – ACEG Mar 14 '17 at 10:49
  • Answered my own question: nope, have to traverse the chain: http://stackoverflow.com/questions/8024149/is-it-possible-to-get-the-non-enumerable-inherited-property-names-of-an-object – ACEG Mar 14 '17 at 10:52
  • Yes you can. If what you want is to retrieve **all** the properties on an object, either own ones or on the prototype chain, you can use a for .. in loop: http://stackoverflow.com/a/208439/7705625 –  Mar 14 '17 at 10:57
  • Interesting! So hasOwnProperty() knows a bit more about the properties available on the whole chain than getOwnPropertyNames()? Will have to try it out, sounds like what I need. Thanks! – ACEG Mar 14 '17 at 11:01
  • I think you're getting confused here. hasOwnProperty tells you whether or not the property is part of the object itself and not the prototype, and getOwnPropertyNames returns all the properties that are part of the object only, not the prototype. What makes this work as intended is the for .. in loop, that retuns **all** the properties, both the own ones or from the prototype. Then using hasOwnProperty you can assert if they're from the object or from down the prototype chain. –  Mar 14 '17 at 11:09
  • Ok -- then my initial understanding was correct: there is no built-in way of getting *all* the properties on an object, whether they were inherited or defined on the object itself. But it's still cool that you don't have to traverse the whole prototype chain manually to find them, and that you can use the for..in construct. They really should put this kind of information in the articles dealing with hasOwnProperty / getOwnPropertyNames! – ACEG Mar 14 '17 at 11:16