js 的原型鏈

從別的博客粘過來的,做個備忘錄,以後好查。

原型鏈(Prototype chain)

Javacript 是一門高度抽象的面向對象(object-oriented)語言, 它沒有類的概念,但是,重用[reuse]這個理念沒什麼不同(某些方面,甚至比class-更加靈活),可以由prototype chain原型鏈來實現。

var a = {
  x: 10,
  calculate: function (z) {
    return this.x + this.y + z
  }
};

var b = {
  y: 20,
  __proto__: a
};

var c = {
  y: 30,
  __proto__: a
};

// 調用繼承過來的方法
b.calculate(30); // 60
c.calculate(40); // 80

原理很簡單:如果在對象b中找不到calculate方法(也就是對象b中沒有這個calculate屬性), 那麼就會沿着原型鏈開始找。如果這個calculate方法在b的prototype中沒有找到,那麼就會沿着原型鏈找到a的prototype,一直遍歷完整個原型鏈。記住,一旦找到,就返回第一個找到的屬性或者方法。因此,第一個找到的屬性成爲繼承屬性。如果遍歷完整個原型鏈,仍然沒有找到,那麼就會返回undefined。

注意一點,this這個值在一個繼承機制中,仍然是指向它原本屬於的對象,而不是從原型鏈上找到它時,它所屬於的對象。例如,以上的例子,this.y是從b和c中獲取的,而不是a。當然,你也發現了this.x是從a取的,因爲是通過原型鏈機制找到的。

這裏寫圖片描述

構造函數(Constructor)

// 構造函數
function Foo(y) {
  // 構造函數將會以特定模式創建對象:被創建的對象都會有"y"屬性
  this.y = y;
}

// "Foo.prototype"存放了新建對象的原型引用
// 所以我們可以將之用於定義繼承和共享屬性或方法
// 所以,和上例一樣,我們有了如下代碼:

// 繼承屬性"x"
Foo.prototype.x = 10;

// 繼承方法"calculate"
Foo.prototype.calculate = function (z) {
  return this.x + this.y + z;
};

// 使用foo模式創建 "b" and "c"
var b = new Foo(20);
var c = new Foo(30);

// 調用繼承的方法
b.calculate(30); // 60
c.calculate(40); // 80

// 讓我們看看是否使用了預期的屬性

console.log(

  b.__proto__ === Foo.prototype, // true
  c.__proto__ === Foo.prototype, // true

  // "Foo.prototype"自動創建了一個特殊的屬性"constructor"
  // 指向a的構造函數本身
  // 實例"b"和"c"可以通過授權找到它並用以檢測自己的構造函數

  b.constructor === Foo, // true
  c.constructor === Foo, // true
  Foo.prototype.constructor === Foo // true

  b.calculate === b.__proto__.calculate, // true
  b.__proto__.calculate === Foo.prototype.calculate // true

);

這裏寫代碼片

執行上下文棧(Execution Context Stack)

在ECMASscript中的代碼有三種類型:global, function和eval。

每一種代碼的執行都需要依賴自身的上下文。當然global的上下文可能涵蓋了很多的function和eval的實例。函數的每一次調用,都會進入函數執行中的上下文,並且來計算函數中變量等的值。eval函數的每一次執行,也會進入eval執行中的上下文。

注意,一個function可能產生無限的上下文環境,因爲一個函數的調用(甚至遞歸)都產生了一個新的上下文環境

一個執行上下文可以激活另一個上下文,就好比一個函數調用了另一個函數(或者全局的上下文調用了一個全局函數),然後一層一層調用下去。邏輯上來說,這種實現方式是棧,我們可以稱之爲上下文堆棧。

當一段程序開始時,會先進入全局執行上下文環境[global execution context], 這個也是堆棧中最底部的元素。此全局程序會開始初始化,初始化生成必要的對象[objects]和函數[functions]. 在此全局上下文執行的過程中,它可能會激活一些方法(當然是已經初始化過的),然後進入他們的上下文環境,然後將新的元素壓入堆棧。在這些初始化都結束之後,這個系統會等待一些事件(例如用戶的鼠標點擊等),會觸發一些方法,然後進入一個新的上下文環境。

執行上下文(Execution Context)

一個執行的上下文可以抽象的理解爲object。每一個執行的上下文都有一系列的屬性(我們稱爲上下文狀態),他們用來追蹤關聯代碼的執行進度。這個圖示就是一個context的結構。

這裏寫圖片描述

除了這3個所需要的屬性(變量對象(variable object),this指針(this value),作用域鏈(scope chain) ),執行上下文根據具體實現還可以具有任意額外屬性。接着,讓我們仔細來看看這三個屬性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章