JavaScript 作用域鏈解析_javascript技巧
JavaScript中有Scope(作用域),Scope chain(作用域鏈),Execute context(執行上下文),Active Object (活動物件),Dynamic Scope(動態作用域),Closure(閉包)這些概念,要理解這些概念,我們從靜態和動態兩個面向去分析。
首先我們寫一個簡單的function來做一個例子:
function add(num1, num2){
var sum = num1 num2;
return sum;
}
我們定義了一個具有兩個形參的add函數。
靜態方面:
當創建add函數的時候,Javascript引擎會創建add函數的Scope chain,這個作用域鏈指向了Global Context(全域上下文)。如果用圖形形象化的表述如下圖:
從上圖可以看出,當add函數創建的時候,作用域鏈就已經創建了,因此可以得出一個結論,函數的作用域鍊是創建函數的時候就已經創建了,而不是動態運行期。下面就來看看動態運行期的時候會發生什麼事。
動態方面:
當執行add函數的時候,JavaScript會建立一個Execute context(執行上下文),執行上下文中就包含了add函數運行期間所需的所有資訊。 Execute context也有自己的Scope chain,當函數運行的時候,JavaScript引擎會先從用add函數的作用域鏈來初始化執行上下文的作用域鏈,然後JavaScript引擎又會創建一個Active Object,這個物件裡麵包含了函數運行期的所有局部變量,參數以及this等變數。
如果形象的描述add函數動態運行期會發生什麼,可以用如下圖來描述:
從上圖可以看出,執行上下文是一個動態的概念,它是當函數運行的時候創建的,同時Active Object物件也是一個動態的概念,它是被執行上下文的作用域鏈所引用的。因此可以得出一個結論:執行上下文和活動物件都是動態概念,並且執行上下文的作用域鍊是由函數作用域鏈初始化的。
上面說了函數作用域和執行上下文作用域,下面接著說一下動態作用域的問題,當在JavaScript通過with語句,try-catch的catch子句,以及eval方法的時候,JavaScript引擎就會動態的改變執行上下文的作用域。下面還是透過一個例子來看:
function initUI(){
with (document){ //avoid!
var bd = body,
links = getElementsByTagName("a"),
i= 0,
len = links.length;
while(i update(links[i ]);
}
getElementById("go-btn").onclick = function(){
start();
};
bd.className = "active";
}
執行上面的initUI函數的時候,JavaScript會動態的建立一個with語句對應的作用域放到執行上下文作用域鏈的最前端,透過下圖可以形象的描述上述過程,下圖紅色標註的區域就顯示了with語句產生的作用域。
最後,我們來看看JavaScript最神秘的Closure(閉包),閉包在JavaScript其實就是一個函數,閉包是在函數運行期被創建的,下面還是以一個實例來看看:
function assignEvents(){
var id = "xdi9592";
document.getElementById("save-btn").onclick = function(event){
saveDocument(id);
};
}
當上面的assignEvents函數被執行的時候,會建立一個閉包,而這個閉包會引用assignEvents作用域中的id變量,如果按照傳統的程式語言的方式,id是儲存在堆疊上的變量,當函數執行完了以後id就消失,那怎麼可能再引用呢?顯然這裡JavaScript採用了另外的方式。下面就來看看JavaScript是如何來實現閉包的。當執行assignEvents函數的時候,JavaScript引擎會建立assignEvents函數執行上下文的作用域鏈,這個作用域鏈包含了assignEvents執行時的活動對象,而同時JavaScript引擎也會建立一個閉包,而閉包的作用域鏈也會引用assignEvent執行時候的活動對象,這樣當assignEvents執行完的時候,雖然它本身執行上下文的作用域鏈不再引用活動對象了,但是閉包還是引用著assignEvents運行期對應的活動對象,這就解釋了JavaScipt內部的閉包機制。可以用下圖形象的表述上面assignEvents函數運行期的情形:
從上面可以看出,當assignEvents函數執行完畢以後,document.getElementById("save-btn").onclick引用了閉包,這樣當用戶點擊save-btn的時候,就會觸發閉包的執行,那麼下面就來看看閉包執行時的情形。前面也說了JavaScript中閉包其實就是函數,因此閉包執行和函數執行時的情形是一致的,透過下圖來形象的描述上述onclick事件所關聯的閉包。
從上圖可以看出JavaScript引擎先建立了閉包的執行上下文,然後用閉包作用域鏈來初始化閉包的執行上下文作用域鏈,最後再將閉包執行時對應的活動物件放入到作用域的最前端,這也進一步驗證了閉包就是函數的論點。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數
