javaScript执行环境、作用域链与闭包
一、執行環境
執行環境定義了變量和函數有權訪問的其他數據,決定了他們各自的行為;每個執行環境都有一個與之關聯的變量對象,環境中定義的所有變量和函數都保存在這個對象中。雖然我們編寫的代碼無法訪問這個對象,但解析器處理數據時會在后臺使用它。
全局執行環境是最外圍的一個執行環境,在web瀏覽器中,全局執行環境被認為是window對象,因此所有全局變量和函數都是作為window對象的屬性和方法創建的。某個執行環境中的所有代碼執行完畢后,該環境被銷毀,保存在其中的所有變量和函數定義也隨之銷毀。
每個函數都有自己的執行環境,當執行流進入一個函數時,函數的環境就會被推入一個環境棧中。而在函數執行之后,棧將其環境彈出,把控制權返回給之前的執行環境。
二、作用域鏈
當代碼在一個環境中執行時,會創建變量對象的一個作用域鏈。作用域鏈的用途是保證對執行環境有權訪問的所有變量和函數的有序訪問。作用域鏈的前端,始終都是當前執行代碼所在環境的變量對象。作用域鏈中的下一個變量對象來自包含環境,而再下一個變量對象則來自下一個包含環境。這樣一直延續到全局執行環境;全局執行環境的變量對象始終都是作用域鏈中的最后一個對象。
標識符解析是沿著作用域鏈一級一級地搜索標識符的過程。搜索過程始終從作用域鏈的前端開始,然后逐級地向后回溯,直至找到標識符為止。
每個環境都可以向上搜索作用域鏈,以查詢變量和函數名;但任何環境都不能通過向下搜索作用域鏈而進入另一個執行環境。
雖然執行環境的類型總共只有兩種——全局和局部(函數),但通過try-catch語句的catch塊和with語句可以延長作用域鏈。這些語句會在作用域鏈的前端臨時增加一個變量對象,該變量對象會在代碼執行后被移除。
js沒有塊級作用域
使用var聲明的變量會自動被添加到最接近的環境中。在函數內部,最接近的環境就是函數的局部環境;在with語句中,最接近的環境是函數環境。如果初始化變量時沒有使用var聲明,該變量會自動被添加到全局環境。
三、閉包
閉包指有權訪問另一個函數作用域中的變量的函數,創建閉包的常見方式,就是在一個函數內部創建另一個函數。
理解閉包:在創建函數時,會創建一個預先包含全局變量的作用域鏈,這個作用域鏈被保存在內部的[[Scope]]屬性中。當調用此函數時,會為函數創建一個執行環境,然后通過復制函數的[[Scope]]屬性中的對象構建起執行環境的作用域鏈,此后又有一個活動對象被創建并被推入執行環境的作用域鏈的前端。因此創建的函數的作用域鏈包含兩個變量對象:本地活動對象和全局變量對象。一般來講,當函數執行完畢后,局部活動對象就會被銷毀,內存中僅保存全局作用域(全局執行環境的變量對象)。在另一個函數內部定義的函數會將外部函數的活動對象添加到它的作用域鏈中。當外部函數執行完畢后,其活動對象不會銷毀,因為內部函數的作用域鏈仍然在引用這個活動對象。當沒有變量引用內部函數時,外部函數的活動對象才會被銷毀。
四、關于this和arguments
this和arguments是函數內部的兩個特殊的對象。
arguments是一個類數組對象,包含著傳入函數中的所有參數,該對象有一個名叫callee的屬性,該屬性是一個指針,指向擁有這個arguments對象的函數。
this對象引用的是函數據以執行的環境對象,是在函數運行時基于函數的執行環境綁定的。當在網頁的全局作用域中調用函數時,this對象引用的就是window,當函數被作為某個對象的方法調用時,this等于那個對象。匿名函數的執行環境具有全局性,因此其this對象通常指向window。每個函數在搜索arguments和this這兩個變量時,只會搜索到其活動對象為止,因此內部函數不可能直接訪問外部函數的這兩個變量。
轉載于:https://www.cnblogs.com/snsart/p/8119662.html
總結
以上是生活随笔為你收集整理的javaScript执行环境、作用域链与闭包的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python, 用filter实现素数
- 下一篇: [ 转载 ] [经典排序算法][集锦]