JS原型與原型鏈

深藍一人發表於2017-11-12

用控制檯輸入如下命令

$ var arr = [];
$ arr.length // 0複製程式碼

問題:為什麼arr會有length屬性?

1. 顯示原型prototype

  • JavaScript中每一個函式,都有一個prototype屬性, 這個屬性指向函式的原型物件
1.1 自定義函式的prototype
var fn = function() {} 
console.log( fn.prototype );
fn.prototype.constructor === fn;   // true複製程式碼

1.2 內建構造器的prototype

Array是什麼?
答:Array是一個函式

那麼Array一定也有一個prototype屬性了

$ Array.prototype.constructor // f Array()
$ Array.prototype.constructor === Array // true
$ Number.prototype.constructor === Number // true
$ String.prototype.constructor === String // true
$ Function.prototype.constructor === Function // true
$ Object.prototype.constructor === Object // true複製程式碼
1.3 改變prototype

結論:

  • 給prototype新增或者刪除屬性會影響所有已經或者未例項化的物件
  • 重寫prototype只會影響新new出來的物件

2. 隱式原型__proto__

  • JavaScript中任意物件都有一個內建屬性proto, 指向建立這個物件的函式(constructor)的prototype
var arr = new Array();
arr.__ptoto__ === Array.prototype // true複製程式碼

根據"JavaScript中任意物件都有一個內建屬性__proto__, 指向建立這個物件的函式(constructor)的prototype",函式Array建立了物件arr,因此arr的__proto__指向Array.prototype。即

  • 此處提一下Object.create(),Object.create接收兩個引數,第一個引數用來作為新物件的隱式原型, 第二個引數是物件的屬性描述符。因此
    var person = {LEG_NUM:2 };
    var xiaoMing = Object.create(person);
    xiaoMing.__proto__ === person; // true複製程式碼
    2.1 改變__proto__

結論

  • 改變arr.proto等價於改變Array.prototype

3. 原型鏈

  • 當我們訪問某個物件中的某個屬性時,如果該物件本身具有這個屬性,則直接使用,如果該物件本身沒有這個屬性,那麼就會沿著__proto__依次查詢

上圖中,訪問obj.z的時候在obj中沒有訪問到,就會沿著__proto__向上查詢,於是在foo.prototype中找到了返回3.

訪問obj.hasOwnProperty()時,同樣在obj中沒有找到這個屬性,沿著__proto__向上查詢,直到在Object.prototype中找到這個屬性。

4. instanceof

instanceof, 左邊是一個物件,右邊必須是一個函式或構造器。它會判斷右邊構造器的prototype屬性是否出現在左邊物件的原型鏈上。

[] instanceof Array // true
[] instanceof Object // true複製程式碼

5. 原型鏈的優缺點

  • 優點: 節省記憶體、方便維護
  • 缺點: 更改原型將影響所有指向它的物件
    以下是《Javascript高階程式設計》中使用到的例子

改變person1的friends,會同時改變person2的friends,因為它們共用一個prototype.這顯然不是我們想要的。可以通過如下方法改進

小結

  • 顯式原型的作用
    用來實現基於原型的繼承與屬性的共享。
  • 隱式原型的作用
    構成原型鏈,同樣用於實現基於原型的繼承。舉個例子,當我們訪問obj這個物件中的x屬性時,如果在obj中找不到,那麼就會沿著__proto__依次查詢。
  • 二者的關係
    隱式原型指向建立這個物件的函式(constructor)的prototype

參考文獻

相關文章