【JavaScript Inheritance】
1、Inheriting properties
JavaScript objects are dynamic "bags" of properties (referred to as own properties). JavaScript objects have a link to a prototype object. When trying to access a property of an object, the property will not only be sought on the object but on the prototype of the object, the prototype of the prototype, and so on until either a property with a matching name is found or the end of the prototype chain is reached.
// Let's assume we have object o, with its own properties a and b: // {a: 1, b: 2} // o.[[Prototype]] has properties b and c: // {b: 3, c: 4} // Finally, o.[[Prototype]].[[Prototype]] is null. // This is the end of the prototype chain, as null, // by definition, has no [[Prototype]]. // Thus, the full prototype chain looks like: // {a: 1, b: 2} ---> {b: 3, c: 4} ---> null console.log(o.a); // 1 // Is there an 'a' own property on o? Yes, and its value is 1. console.log(o.b); // 2 // Is there a 'b' own property on o? Yes, and its value is 2. // The prototype also has a 'b' property, but it's not visited. // This is called "property shadowing." console.log(o.c); // 4 // Is there a 'c' own property on o? No, check its prototype. // Is there a 'c' own property on o.[[Prototype]]? Yes, its value is 4. console.log(o.d); // undefined // Is there a 'd' own property on o? No, check its prototype. // Is there a 'd' own property on o.[[Prototype]]? No, check its prototype. // o.[[Prototype]].[[Prototype]] is null, stop searching, // no property found, return undefined.
2、Inheriting "methods"
JavaScript does not have "methods" in the form that class-based languages define them. In JavaScript, any function can be added to an object in the form of a property. An inherited function acts just as any other property, including property shadowing as shown above (in this case, a form of method overriding).
When an inherited function is executed, the value of this
points to the inheriting object, not to the prototype object where the function is an own property.
var o = { a: 2, m: function() { return this.a + 1; } }; console.log(o.m()); // 3 // When calling o.m in this case, 'this' refers to o var p = Object.create(o); // p is an object that inherits from o p.a = 4; // creates an own property 'a' on p console.log(p.m()); // 5 // when p.m is called, 'this' refers to p. // So when p inherits the function m of o, // 'this.a' means p.a, the own property 'a' of p
3、常见的继承链
var o = {a: 1}; // The newly created object o has Object.prototype as its [[Prototype]] // o has no own property named 'hasOwnProperty' // hasOwnProperty is an own property of Object.prototype. // So o inherits hasOwnProperty from Object.prototype // Object.prototype has null as its prototype. // o ---> Object.prototype ---> null var a = ['yo', 'whadup', '?']; // Arrays inherit from Array.prototype // (which has methods like indexOf, forEach, etc.) // The prototype chain looks like: // a ---> Array.prototype ---> Object.prototype ---> null function f() { return 2; } // Functions inherit from Function.prototype // (which has methods like call, bind, etc.) // f ---> Function.prototype ---> Object.prototype ---> null
4、Object.create 创建原型链
var a = {a: 1}; // a ---> Object.prototype ---> null var b = Object.create(a); // b ---> a ---> Object.prototype ---> null console.log(b.a); // 1 (inherited) var c = Object.create(b); // c ---> b ---> a ---> Object.prototype ---> null var d = Object.create(null); // d ---> null console.log(d.hasOwnProperty); // undefined, because d doesn't inherit from Object.prototype
5、hasOwnProperty
To check whether an object has a property defined on itself and not somewhere on its prototype chain, it is necessary to use the hasOwnProperty
method which all objects inherit from Object.prototype
.
hasOwnProperty
is the only thing in JavaScript which deals with properties and does not traverse the prototype chain.
__proto__
(now deprecated).
Since ECMAScript 6, the [[Prototype]]
is accessed using the accessorsObject.getPrototypeOf()
and Object.setPrototypeOf()
.
Setting a property to an object creates an own property. The only exception to the getting and setting behavior rules is when there is an inherited property with a getter or a setter.
【Getter & Setter】
【Object.defineProperty】