1. 程式人生 > >執行環境、作用域、作用域鏈、調用對象、閉包

執行環境、作用域、作用域鏈、調用對象、閉包

作用 嵌套 頂部 擁有 函數 新的 保持 綁定 全局

執行環境 :  每調用一個函數時(執行函數時),系統會為該函數創建一個封閉的局部的運行環境,即該函數的執行環境。函數總是在自己的執行環境中執行,如讀寫局部變量、函數參數、運行內部邏輯。創建執行環境的過程包含了創建函數的作用域,函數也是在自己的作用域下執行的。從另一個角度說,每個函數執行環境都有一個作用域鏈,子函數的作用域鏈包括它的父函數的作用域鏈。關於作用域、作用域鏈請看下面。

  作用域、作用域鏈、調用對象:   函數作用域分為詞法作用域和動態作用域。   詞法作用域是函數定義時的作用域,即靜態作用域。當一個函數定義時,他的詞法作用域就確定了,詞法作用域說明的是在函數結構的嵌套關系下,函數作用的範圍。這個時候也就形成了該函數的作用域鏈。作用域鏈就是把這些具有嵌套層級關系的作用域串聯起來。函數的內部[[scope]]屬性指向了該作用域鏈。   動態作用域是函數調用執行時的作用域。當一個函數被調用時,首先將函數內部[[scope]]屬性指向了函數的作用域鏈,然後會創建一個調用對象,並用該調用對象記錄函數參數和函數的局部變量,將其置於作用域鏈頂部。動態作用域就是通過把該調用對象加到作用域鏈的頂部來創建的,此時的[[scope]]除了具有定義時的作用域鏈,還具有了調用時創建的調用對象。換句話說,執行環境下的作用域等於該函數定義時就確定的作用域鏈加上該函數剛剛創建的調用對象,從而也形成了新的作用域鏈。所以說是動態的作用域,並且作用域鏈也隨之發生了變化。再看這裏的作用域,其實是一個對象鏈,這些對象就是函數調用時創建的調用對象,以及他上面一層層的調用對象直到最上層的全局對象。    譬如全局環境下的函數A內嵌套了一個函數B,則該函數B的作用域鏈就是:函數B的作用域—>函數A的作用域—>全局window的作用域。當函數B調用時,尋找某標識符,會按函數B的作用域—>函數A的作用域—>全局window的作用域去尋找,實際上是按函數B的調用對象—>函數A的調用對象—>全局對象這個順序去尋找的。也就是說當函數調用時,函數的作用域鏈實際上是調用對象鏈。

  閉包 :  在動態執行環境中,數據實時地發生變化,為了保持這些非持久型變量的值,我們用閉包這種載體來存儲這些動態數據(看完下面的應用就會很好的體會這句話)。閉包的定義:所謂“閉包”,指的是一個擁有許多變量和綁定了這些變量的環境的表達式(通常是一個函數),因而這些變量也是該表達式的一部分。   閉包就是嵌套在函數裏面的內部函數,並且該內部函數可以訪問外部函數中聲明的所有局部變量、參數和其他內部函數。當該內部函數在外部函數外被調用,就生成了閉包。(實際上任何函數都是全局作用域的內部函數,都能訪問全局變量,所以都是window的閉包)

執行環境、作用域、作用域鏈、調用對象、閉包