This blog post examines how the prototype chain of an object affects assignments to its properties. It provides a more detailed look than the previous, more comprehensive, blog post “Properties in JavaScript: definition versus assignment”.
> var proto = { foo: 1 }; > var obj = { __proto__: proto, bar: 2 }; > obj.foo 1 > obj.bar 2We used the special property __proto__ [1] to create the chain (which is not yet supported by all browsers). The prototype chain of obj comprises three objects: It starts with obj, continues with proto and ends with Object.prototype. Object.prototype is the constructor prototype of Object and a member of most (but not all [2]) prototype chains:
> Object.prototype.isPrototypeOf({}) true > Object.prototype.isPrototypeOf([]) true > Object.prototype.isPrototypeOf(new Date()) trueIt is also the final member:
> Object.getPrototypeOf(Object.prototype) nullObject.prototype gives objects many standard methods such as toString() and hasOwnProperty().
> obj.foo = 3; > obj.foo 3 > obj.hasOwnProperty("foo") true > proto.foo 1The idea is that a prototype introduces an initialization value that is the same for all instances. If assigning to the property of an instance could change that value then all instances would have different initialization values afterwards. To prevent this from happening while still allowing changing the initial value, assignment only lets you change an existing own property. If no such property exists, it is created automatically.
var obj = { __proto__: { get foo() { return 1; }, set foo(x) { console.log("Setter called: "+x); } } };Then assigning to foo calls the setter instead of creating an own property and reading it calls the getter:
> obj.foo = 2; Setter called: 2 > obj.foo 1You can prevent the property assignment by only providing a getter:
var obj = { __proto__: { get foo() { return 1; } } };The assignment quietly fails in non-strict mode and throws an error in strict mode [4]:
> (function () { "use strict"; obj.foo = 2; }()); TypeError: Cannot set property foo of obj which has only a getter
var proto = Object.defineProperty({}, "foo", { value: 1, writable: false }); var obj = { __proto__: proto };It is impossible to assign to obj.foo:
> (function () { "use strict"; obj.foo = 2; }()); TypeError: obj.foo is read-onlyThis is in line with how a getter-only property works and conforms to the metaphor introduced above: again, the prototype property is shared state, but this time, we want to prevent its values from being changed. If you wanted to create an own property foo in obj, you could do so via Object.defineProperty() and Object.defineProperties() [5].