In mdn's doc's for the prototype chain, it states
All objects inherit the
Object.prototype.__proto__
setter, which can be used to set the [[Prototype]] of an existing object (if the__proto__
key is not overridden on the object).
It then goes on to say that
Object.prototype.__proto__
accessors are non-standard and deprecated. You should almost always use Object.setPrototypeOf instead.
Along with this example:
const obj = {};
// DON'T USE THIS: for example only.
obj.__proto__ = { barProp: 'bar val' };
obj.__proto__.__proto__ = { fooProp: 'foo val' };
console.log(obj.fooProp);
console.log(obj.barProp);
The part that is confusing is they start the docs out with this example:
const o = {
a: 1,
b: 2,
// __proto__ sets the [[Prototype]]. It's specified here
// as another object literal.
__proto__: {
b: 3,
c: 4,
},
};
Stating that,
{ __proto__: ... }
syntax is different from theobj.__proto__
accessor: the former is standard and not deprecated.
How is { __proto__: ...}
different from obj.__proto__
? Both are properties of an object, and I'm not quite clear on what the difference is here.
CodePudding user response:
It's just the way the syntax was designed. (See here and here.) Assigning to the __proto__
of an existing object is deprecated, but specifying a __proto__
at the point when the object is created is not.
One reason for why an object literal can have it but doing so with an already existing object is not recommended is because, as MDN says on the subject of changing an object's prototype:
Warning: Changing the
[[Prototype]]
of an object is, by the nature of how modern JavaScript engines optimize property accesses, currently a very slow operation in every browser and JavaScript engine. In addition, the effects of altering inheritance are subtle and far-flung, and are not limited to the time spent in theObject.setPrototypeOf(...)
statement, but may extend to any code that has access to any object whose[[Prototype]]
has been altered. You can read more in JavaScript engine fundamentals: optimizing prototypes.Because this feature is a part of the language, it is still the burden on engine developers to implement that feature performantly (ideally). Until engine developers address this issue, if you are concerned about performance, you should avoid setting the
[[Prototype]]
of an object. Instead, create a new object with the desired[[Prototype]]
usingObject.create()
.
In well-designed code, there should not be a need to dynamically change the internal prototype of an already existing object. In contrast, it's completely normal to want to specify an internal prototype when creating an object initially.
(Setting a new internal prototype of an object can be done with setPrototypeOf
, which is not recommended, and by assigning to the object's __proto__
, which is not only not recommended, but deprecated as well)