一張圖徹底理解Javascript原型鏈

陳贇發表於2018-06-22

程式碼

講解用到的程式碼很簡單,如下

function Foo(){
    //屬性和方法
}
var f1 = new Foo();
var f2 = new Foo(); 
var o1 = new Object();
var o2 = new Object();
複製程式碼

基礎瞭解

一切皆物件,物件又可以分為兩類:

  1. 普通物件 ,除了函式物件之外的物件都是,包括new函式物件()產生的例項,普通物件沒有prototype,也就沒有繼承和原型鏈一說。
  2. 函式物件 ,包括兩種:
  • 由function創造出來的函式:

          function f1() {
          } // 匿名函式
          var f2 = function() {
          }
          var f3 = new Function('x','console.log(x)');
          // 以上都是函式物件
    複製程式碼
  • 系統內建的函式物件: FunctionObject、Array、String、Number ,Function其實充當了函式物件的構造器,比如Object物件的構造原始碼其實是Function Object() {[native code]}的形式,這一點對於理解原型鏈很重要。

進入正題

一張圖徹底理解Javascript原型鏈
上圖從結構上分為例項物件、Functions函式物件、prototype原型物件三部分,圖中f1、f2的原型鏈我特意標成了紅色,Foo的原型鏈為紫色。

每個物件都有__proto__屬性,用於儲存繼承得來的方法和屬性;每個函式物件都有prototype屬性,用於繼承,將其中定義的屬性和方法傳遞給‘後代’(比如例項化)。

如何實現原型繼承

f1為何有Foo、Object的原型方法,其實就是通過原型鏈繼承。繼承的過程可以表示為f1.__proto__ = Foo.prototype,即物件.__proto__ = 構造器.prototype

new例項實現繼承的過程其實與上面原理相同,new的過程可以拆解為下面幾個步驟:

var temp = {};
temp.__proto__ = Foo.prototype; // 原型繼承
var f1 = Foo.call(temp);
return f1;
複製程式碼

找出原型鏈

1) f1的原型鏈(紅色虛線)。

  1. f1為普通物件,它的構造器為Foo,以Foo為原型,原型鏈第一鏈為f1.__proto__ == Foo.prototype
  2. Foo.prototype(注意這邊不是Foo)為json物件,即普通物件,構造器為Object,以Object為原型,得出原型鏈第二鏈Foo.prototype.__proto__ == Object.prototype;
  3. Object.prototype以Null為原型,原型鏈第三鏈為Object.prototype.__proto__ == null

 f1的原型鏈可以用圖形表示:

一張圖徹底理解Javascript原型鏈

 可以在瀏覽器console列印驗證:

一張圖徹底理解Javascript原型鏈

2) Foo的原型鏈(紫色虛線)

  1. Foo為函式物件,它的構造器為Function,以Function為原型,原型鏈第一鏈為Foo.__proto__ == Function.prototype;
  2. Function.prototype為json物件,即普通物件,構造器為Object,以Object為原型,原型鏈第二鏈為Function.prototype.__proto__ == Object.prototype;
  3. 最後Object.prototype以Null為原型,原型鏈第三鏈為Object.prototype.__proto__ == null;

 Foo的原型鏈可以用圖形表示為:

一張圖徹底理解Javascript原型鏈
 可以在瀏覽器console列印驗證:

一張圖徹底理解Javascript原型鏈

3)小結

列出兩種原型鏈的目的是:

當js引擎執行物件的屬性或方法時,先查詢物件本身是否存在該方法,如果不存在則會在原型鏈上查詢。

因而f1擁有Foo、Object的原型方法,Foo擁有Function、Object的原型方法。

注意,雖然f1原型鏈其中有一鏈是涉及到函式物件Foo,但f1並不擁有Function的原型方法,因為原型鏈並沒有延伸到Function。

比如下圖中bind是Function的原型方法,f1並沒有擁有。

一張圖徹底理解Javascript原型鏈

總結

如何找出一個物件的原型鏈,只需要兩步

  1. 判斷物件是普通物件還是函式物件,得出物件的構造器
  2. 物件.proto = 構造器.prototype

關於最上面的圖形,只剩Object和Function的特殊關係和建構函式constructor沒有講到, 瞭解Object和Function的關係,戳這兒~

如果有講不清和講錯了的地方,請幫我指出來,我也跟大家一起在學習中,請輕噴(●ˇ∀ˇ●)

相關文章