This article will study how the prototype chain of an object affects the attribute assignment operation of the object. this article elaborates in detail a knowledge point mentioned in the previous article "[translation] attributes in JavaScript: The difference between definition and value assignment.
Prototype chain
Each object has a prototype chain that contains one or more objects. This object is the starting object of this prototype chain. all attributes of all objects in the prototype chain can be accessed by this object. for example:
- > var proto = { foo: 1 };
- > var obj = { __proto__: proto, bar: 2 };
- > obj.foo
- 1
- > obj.bar
- 2
We used the special attribute _ proto _ to create the prototype chain (this property is not widely supported by all browsers ). the prototype chain of Object obj contains three objects: obj at the beginning, followed by proto, and Object at the end. prototype. object. prototype is the prototype Object of the Object constructor. Most prototype chains contain it (most, but not all ):
- > Object.prototype.isPrototypeOf({})
- true
- > Object.prototype.isPrototypeOf([])
- true
- > Object.prototype.isPrototypeOf(new Date())
- true
And it is the end object of the prototype chain:
- > Object.getPrototypeOf(Object.prototype)
- null
Many standard methods of common objects are inherited from Object. prototype, such as toString () and hasOwnProperty ().
Assign values to attributes
If you assign a value to an attribute, you can only modify the starting object (that is, the object itself) on the prototype chain. If your attributes already exist, you can change the value of this attribute. Otherwise, create this new property:
- > obj.foo = 3;
- > obj.foo
- 3
- > obj.hasOwnProperty("foo")
- true
- > proto.foo
- 1
The purpose of this design is that a prototype can introduce a common initial value (the value of the inherited attribute) to all its instances ). if you assign a value to the attribute of the same name for one instance to change the public attribute value on the prototype, the initial values of all instances will be changed. to prevent this, you can also modify the initial values of a single instance. The attribute assignment Operation is designed to only allow you to change the values of an existing attribute. if this attribute does not exist, it is automatically created and assigned a value.
Accessors and prototype links
An accessor attribute that exists on the prototype chain [3] can block "creating attributes of the same name on the starting object of the prototype chain ". assume that object obj inherits an object with getter and setter:
- var obj = {
- __proto__: {
- get foo() {
- return 1;
- },
- set foo(x) {
- console.log("Setter called: "+x);
- }
- }
- };
If you assign a value to the property foo of object obj, it will call the setter accessor on its prototype, instead of creating its own property foo for obj. Similarly, if you read the foo attribute of object obj, it will also call the getter accessors on its prototype:
- > obj.foo = 2;
- Setter called: 2
- > obj.foo
- 1
If you want to disable the value assignment operation of this attribute (that is, read-only), you can disable setter:
- var obj = {
- __proto__: {
- get foo() {
- return 1;
- }
- }
- };
-
In non-strict mode, such a value assignment operation will silently fail. In strict mode, an exception will be thrown:
- > (function () { "use strict"; obj.foo = 2; }());
- TypeError: Cannot set property foo of obj which has only a getter
Read-only attribute on the prototype chain
If the starting object on the prototype chain inherits a read-only attribute, you cannot change the value of this attribute by assigning values. For example, the following code:
- var proto = Object.defineProperty({},
- "foo",
- {
- value: 1,
- writable: false
- });
- var obj = { __proto__: proto };
You cannot assign values to obj. foo:
- > (function () { "use strict"; obj.foo = 2; }());
- TypeError: obj.foo is read-only
This is exactly the same as the performance of the accessor attribute of only getter. this time, the prototype attributes can also be used as an initial shared value. The difference is that we should prevent a single instance from changing its own initial value. if you want to create a property foo for obj, you can use Object. defineProperty () and Object. defineProperties () to complete.
Http://www.2ality.com/2012/11/property-assignment-prototype-chain.html.