Green
Green

Reputation: 30805

Why a property in an object is undefined, although it exists in object's __proto__?

First, here is an example that works as expected:

let a = { foo: 10 }
let b = { bar: 20 }
a.__proto__ = b

// returns value from prototype just fine
a.bar; // 20

And here is an example that is under the question, that does not work as expected. Why?

// "a" has no prototype when created this way
let a = Object.create(null);

// "b" has prototype and it is a JS native Object with a whole slew of its native props
let b = {};

// assign "a" a prototype
a.__proto__ = b;

// let's try
a.toString; // undefined

// but...
a.__proto__ .toString; // function toString() { [native code] }

Why a.toString returns undefined although a prototype with that property was assigned to it?

Upvotes: 2

Views: 126

Answers (1)

Ry-
Ry-

Reputation: 224942

__proto__ is a getter and setter on Object.prototype.

> Object.getOwnPropertyDescriptor(Object.prototype, '__proto__')
{ get: [Function: get __proto__],
  set: [Function: set __proto__],
  enumerable: false,
  configurable: true }

If you create an object that doesn’t inherit from Object.prototype, it doesn’t have that special property, and setting __proto__ will create a completely normal property like any other.

Here’s Object.prototype.__proto__’s setter setting a prototype instead of creating a property:

> var a = {};
> a.__proto__ = { foo: 'bar' };
> Object.prototype.hasOwnProperty.call(a, '__proto__')
false

and here’s that setter not being used because Object.prototype isn’t in the chain:

> var b = Object.create(null);
> b.__proto__ = { foo: 'bar' };
> Object.prototype.hasOwnProperty.call(b, '__proto__')
true

Use Object.setPrototypeOf instead (always):

Object.setPrototypeOf(a, b);

Upvotes: 1

Related Questions