函數的的生命週期分為創建和激活階段(調用時),讓我們詳細研究它。
函數創建
眾所周知,在進入上下文時函數聲明放到變數/活動(VO/AO)物件中。讓我們看看在全域上下文中的變數和函數宣告(這裡變數物件是全域物件自身,我們還記得,對吧?)
var x = 10; function foo() { var y = 20; alert(x + y); } foo(); // 30
在函數啟動時,我們得到正確的(預期的)結果-30 。但是,有一個很重要的特點。
此前,我們僅談到有關當前上下文的變數物件。這裡,我們看到變數「y」在函數「foo」中定義(意味著它在foo上下文的AO中),但是變數「x」並未在「foo」上下文中定義,相應地,它也不會加入到“foo”的AO中。乍一看,變數“x”相對於函數“foo”根本就不存在;但正如我們在下面看到的——也僅僅是“一瞥”,我們發現,“foo”上下文的活動物件中僅包含一個屬性——“y”。
fooContext.AO = { y: undefined // undefined – 进入上下文的时候是20 – at activation };
函數「foo」如何存取到變數「x」?理論上函數應該能存取一個更高一層上下文的變數物件。實際上它正是這樣,這種機制是透過函數內部的[[scope]]屬性來實現的。
[[scope]]是所有父變數物件的層級鏈,處於目前函數上下文之上,在函數建立時存於其中。
注意這重要的一點——[[scope]]在函數創建時被儲存——靜態(不變的),永遠永遠,直到函數銷毀。即:函數可以永不調用,但[[scope]]屬性已經寫入,並儲存在函數物件中。
另外一個需要考慮的是-與作用域鏈對比,[[scope]]是函數的一個屬性而不是上下文。考慮到上面的例子,函數「foo」的[[scope]]如下:
foo.[[Scope]] = [ globalContext.VO // === Global ];
舉例來說,我們用通常的ECMAScript 陣列展現作用域和[[scope]]。
繼續,我們知道在函數呼叫時進入上下文,這時候活動物件被創建,this和作用域(作用域鏈)被確定。讓我們詳細考慮這一刻。
函數啟動
正如在定義中說到的,進入上下文創建AO/VO之後,上下文的Scope屬性(變數查找的一個作用域鏈)作如下定義:
Scope = AO|VO + [[Scope]]
上面程式碼的意思是:活動對象是作用域數組的第一個對象,即加入到作用域的前端。
Scope = [AO].concat([[Scope]]);
這個特點對於標示符解析的處理來說很重要。標示符解析是一個處理過程,用來決定一個變數(或函數宣告)屬於哪個變數物件。
這個演算法的回傳值中,我們總是有一個引用型,它的base元件是對應的變數物件(或若未找到則為null),屬性名稱元件是向上尋找的標示符的名稱。引用類型的詳細資訊在後面已討論。
標識符解析過程包含與變數名稱對應屬性的查找,即作用域中變數物件的連續查找,從最深的上下文開始,繞過作用域鏈直到最上層。
這樣一來,在向上查找中,一個上下文中的局部變數較之於父作用域的變數擁有較高的優先權。萬一兩個變數有相同的名稱但來自不同的作用域,那麼第一個被發現的是在最深作用域中。
我們用一個稍微複雜的例子來描述上面講到的這些。
var x = 10; function foo() { var y = 20; function bar() { var z = 30; alert(x + y + z); } bar(); } foo(); // 60
對此,我們有如下的變數/活動對象,函數的的[[scope]]屬性以及上下文的作用域鏈:
全局上下文的變數對像是:
globalContext.VO === Global = { x: 10 foo: <reference to function> };
在「foo」創建時, 「foo」的[[scope]]屬性是:
foo.[[Scope]] = [ globalContext.VO ];
在「foo」活化時(進入上下文),「foo」上下文的活動物件是:
fooContext.AO = { y: 20, bar: <reference to function> };
「foo」上下文的作用域鏈為:
fooContext.Scope = fooContext.AO + foo.[[Scope]] // i.e.: fooContext.Scope = [ fooContext.AO, globalContext.VO ];
內部函數「bar」建立時,其[[scope]]為:
bar.[[Scope]] = [ fooContext.AO, globalContext.VO ];
在「bar」啟動時,「bar」上下文的活動物件為:
barContext.AO = { z: 30 };
「bar」上下文的作用域鏈為:
barContext.Scope = barContext.AO + bar.[[Scope]] // i.e.: barContext.Scope = [ barContext.AO, fooContext.AO, globalContext.VO ];
對「x」、「y」、「z」的識別碼解析如下:
- "x" -- barContext.AO // not found -- fooContext.AO // not found -- globalContext.VO // found - 10 - "y" -- barContext.AO // not found -- fooContext.AO // found - 20 - "z" -- barContext.AO // found - 30
以上就是JavaScript作用域鏈其二:函數的生命週期的內容,更多相關內容請關注PHP中文網(www .php.cn)!

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。1.Python以简洁语法和丰富库生态著称,适用于数据分析和Web开发。2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。

JavaScript不需要安裝,因為它已內置於現代瀏覽器中。你只需文本編輯器和瀏覽器即可開始使用。 1)在瀏覽器環境中,通過標籤嵌入HTML文件中運行。 2)在Node.js環境中,下載並安裝Node.js後,通過命令行運行JavaScript文件。


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Dreamweaver CS6
視覺化網頁開發工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

SublimeText3 Linux新版
SublimeText3 Linux最新版