一、原型(屬性)__proto__
每個實例對象(obj)的私有屬性,在ECMAScript中規定obj.[[Prototype]]符號表示實例對象的原型。但早期並沒有統一規範,所以大部分瀏覽器自己實現了該私有屬性,多以__proto__的方式進行訪問,該屬性指向實例對象obj的構造函數的原型對象(prototype)。
二、原型對象 prototype
每個構造函數(本身也是對象)有一個屬性prototype,表示它的原型對象。其本身作爲一個對象也具有一個原型屬性__proto__。
三、原型鏈 prototype chain
向上述這樣,一個實例對象-->構造函數的原型對象-->構造函數的原型對象的構造函數原型對象-->...-->null,就構成了一條原型鏈。根據定義,null沒有原型(屬性),作爲這個原型鏈中的最後一個環節。舉個例子
const a = {a: 1} // a ---> Object.prototype ---> null
console.log(a.__proto__ === Object.prototype) // true
console.log(Object.getPrototypeOf(a) === Object.prototype) // true
console.log(a.__proto__.__proto__ === null) // true
console.log(Object.getPrototypeOf(Object.getPrototypeOf(a)) === null) // true
四、ES6對原型的實現
在ES6中,__proto__這一私有屬性規範化,通過Object.getPrototypeOf(obj)和Object.setPrototypeOf(obj)來訪問。
五、原型繼承
Object.create(obj) 新建一個對象實例,這個對象實例的原型(屬性)指向obj。舉個例子
const b = Object.create(a) // b ---> a ---> Object.prototype ---> null
console.log(b.__proto__ === a) // true
console.log(Object.getPrototypeOf(b) === a) // true
console.log(b.__proto__.__proto__ === Object.prototype) // true
console.log(Object.getPrototypeOf(Object.getPrototypeOf(b)) === Object.prototype) // true
console.log(b.__proto__.__proto__.__proto__ === null) // true
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(b))) === null) // true
六、總結
JS一切都是對象,JS只有這一種“結構”,每個對象都有一個私有屬性稱之爲原型(__proto__),它指向該對象的構造函數的原型對象(prototype),而原型對象也有原型(__proto__),一直到最後指向null,null沒有原型,就到了原型鏈的盡頭。