摘要:執(zhí)行環(huán)境對象和作用域鏈執(zhí)行環(huán)境,又稱執(zhí)行上下文,是指一個函數(shù)在執(zhí)行的時候所能直接引用的變量等的一個集合。為了解釋作用域鏈的機制,我們再來引入一個屬性的概念。而函數(shù)的執(zhí)行環(huán)境對象作用域鏈保存了函數(shù)在執(zhí)行時能解析到的變量。
執(zhí)行環(huán)境對象和作用域鏈
執(zhí)行環(huán)境,又稱執(zhí)行上下文,是指一個函數(shù)在執(zhí)行的時候所能直接引用的變量等的一個集合。
在JavaScript引擎中,執(zhí)行環(huán)境是由一類特殊的對象——執(zhí)行環(huán)境對象——來實現(xiàn)的。由于一個函數(shù)執(zhí)行的時候可能對應(yīng)不同的上下文,所以每次函數(shù)執(zhí)行的時候都會由引擎為該函數(shù)創(chuàng)建一個獨一無二的執(zhí)行環(huán)境對象。函數(shù)執(zhí)行完畢時,由垃圾回收(GC)機制來決定是否將該執(zhí)行環(huán)境對象回收。
為了區(qū)別執(zhí)行環(huán)境和執(zhí)行上下文,我將下文中的執(zhí)行環(huán)境稱作“執(zhí)行上下文”。
注意:全局環(huán)境(全局作用域所在的環(huán)境)雖然不是一個函數(shù),但是其中的代碼執(zhí)行時,也會有一個相應(yīng)的執(zhí)行環(huán)境對象與之對應(yīng)。
不同執(zhí)行環(huán)境中的變量是存在依賴關(guān)系的。
例如:一個全局執(zhí)行環(huán)境下創(chuàng)建的函數(shù)在執(zhí)行時,其執(zhí)行環(huán)境需要知道全局執(zhí)行環(huán)境中的變量:window、document、以及其他聲明的全局變量(注意:未聲明的變量作為window對象的屬性,和聲明過的全局變量有略微的不同之處)。熟悉函數(shù)作用域概念的同學(xué),不難理解這種依賴關(guān)系。
這種依賴關(guān)系是通過執(zhí)行環(huán)境對象中的一個特殊的屬性,引用創(chuàng)建該函數(shù)時的所對應(yīng)的執(zhí)行環(huán)境對象來實現(xiàn)的。由于這種引用關(guān)系可以形成一條引用鏈,一個函數(shù)執(zhí)行時,引擎對變量的解析就是通過對執(zhí)行環(huán)境對象引用鏈的遍歷來解析確定的。
這個引用鏈有個高大上的、經(jīng)常聽到的名字——作用域鏈。
為了解釋作用域鏈的機制,我們再來引入一個scope屬性的概念。
函數(shù)對象的scope屬性我們知道,JavaScript的函數(shù)是Function構(gòu)造函數(shù)的實例,本質(zhì)是一類特殊的對象。某一個對象只可能在某一個獨一無二的執(zhí)行上下文中創(chuàng)建,但是函數(shù)對象會在不同的執(zhí)行上下文中執(zhí)行。
函數(shù)對象有很多屬性,其中一個就是只有在JavaScript引擎中可見的scope屬性。這個scope屬性指向創(chuàng)建該函數(shù)時對應(yīng)的執(zhí)行環(huán)境對象。
該函數(shù)執(zhí)行的時候,使用函數(shù)內(nèi)的函數(shù)作用域變量創(chuàng)建一個新執(zhí)行環(huán)境對象,并且引用scope屬性指向的執(zhí)行環(huán)境對象。這個執(zhí)行環(huán)境對象和該函數(shù)的執(zhí)行上下文相對應(yīng)。
這三者對應(yīng)關(guān)系如下圖所示:
但是scope屬性依然引用創(chuàng)建這個函數(shù)的執(zhí)行環(huán)境對象,原因跟上面的解釋是一樣的:
函數(shù)執(zhí)行時變量解析一個函數(shù)只能在某個特定的執(zhí)行上下文中創(chuàng)建,但是會在不同的執(zhí)行上下文中執(zhí)行。
從作用域鏈的角度解釋:首先從該函數(shù)所對應(yīng)的執(zhí)行環(huán)境對象中搜索該變量,如果沒有則沿著作用域鏈繼續(xù)搜索,直到找到為止。然后將數(shù)據(jù)取出或者存儲。
這里有一個優(yōu)化問題:不要在代碼中過多的引用作用域鏈中離頭結(jié)點(即當前執(zhí)行環(huán)境對象)較遠的結(jié)點中的變量。解決辦法:將這個非頭結(jié)點中的變量賦值給函數(shù)局部變量變?yōu)轭^結(jié)點中的變量,這樣就不需要每次都去搜索作用域鏈了。
題外話:thisthis可以認為是一個特殊的變量,代表函數(shù)的調(diào)用者。每一個執(zhí)行環(huán)境對象中都有一個this,但是變量搜索時,只需搜索當前的執(zhí)行環(huán)境對象就可以找到這個變量。當需要找到作用域鏈中非頭結(jié)點的this時,需要將其保存為其他特定的能被引用到的局部變量來處理。
閉包現(xiàn)在我們可以看看小宇宙中的黑魔法了。
函數(shù)B在函數(shù)A中被返回。那么創(chuàng)建函數(shù)B的執(zhí)行環(huán)境對象就是函數(shù)A對應(yīng)的執(zhí)行環(huán)境對象。那么函數(shù)B的scope對象會保存函數(shù)A的執(zhí)行環(huán)境對象。
而函數(shù)A的執(zhí)行環(huán)境對象作用域鏈保存了函數(shù)A在執(zhí)行時能解析到的變量。所以函數(shù)B中就能通過其scope屬性訪問函數(shù)A的執(zhí)行環(huán)境中的變量。
假設(shè)函數(shù)B的調(diào)用者無法訪問函數(shù)A中的變量,那么它只能通過函數(shù)B的行為來獲得函數(shù)A中的變量狀態(tài)。
此時函數(shù)B由于其scope屬性保存了函數(shù)A的執(zhí)行環(huán)境對象的作用域鏈,從而形成一個閉包。
結(jié)束一點微小的見解。
本文涉及JavaScript界的敏感話題,故而,如有紕漏,歡迎吐槽。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/90860.html
摘要:本期推薦文章從作用域鏈談閉包,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。推薦理由這是一篇譯文,深入淺出圖解作用域鏈,一步步深入介紹閉包。作用域鏈的頂端是全局對象,在全局環(huán)境中定義的變量就會綁定到全局對象中。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周開始前端進階的第二期,本周的主題是作用域閉包,今天是第6天。 本...
摘要:變量對象也是有父作用域的。作用域鏈的頂端是全局對象。當函數(shù)被調(diào)用的時候,作用域鏈就會包含多個作用域?qū)ο?。當函?shù)要訪問時,沒有找到,于是沿著作用域鏈向上查找,在的作用域找到了對應(yīng)的標示符,就會修改的值。 一、概要 對于閉包的定義(紅寶書P178):閉包就是指有權(quán)訪問另外一個函數(shù)的作用域中的變量的函數(shù)。 關(guān)鍵點: 1、閉包是一個函數(shù) 2、能夠訪問另外一個函數(shù)作用域中的變量 二、閉包特性 對...
摘要:閉包面試題解由于作用域鏈機制的影響,閉包只能取得內(nèi)部函數(shù)的最后一個值,這引起的一個副作用就是如果內(nèi)部函數(shù)在一個循環(huán)中,那么變量的值始終為最后一個值。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進階的第二期,本周的主題是作用域閉包,今天是第8天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了...
摘要:使用上一篇文章的例子來說明下自由變量進階期深入淺出圖解作用域鏈和閉包訪問外部的今天是今天是其中既不是參數(shù),也不是局部變量,所以是自由變量。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進階的第二期,本周的主題是作用域閉包,今天是第7天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了解本進階計...
摘要:前言這段時間一直在消化作用域鏈和閉包的相關(guān)知識。而作用域鏈則是這套規(guī)則這套規(guī)則的具體運行。是變量對象的縮寫那這樣放有什么好處呢我們知道作用域鏈保證了當前執(zhí)行環(huán)境對符合訪問權(quán)限的變量和函數(shù)的有序訪問。 前言:這段時間一直在消化作用域鏈和閉包的相關(guān)知識。之前看《JS高程》和一些技術(shù)博客,對于這些概念的論述多多少少不太清楚或者不太完整,包括一些大神的技術(shù)文章。這也給我的學(xué)習(xí)上造成了一些困惑,...
閱讀 4390·2023-04-25 16:32
閱讀 2383·2021-09-28 09:36
閱讀 2191·2021-09-06 15:02
閱讀 843·2021-09-02 15:21
閱讀 1066·2019-08-30 15:56
閱讀 3666·2019-08-30 15:45
閱讀 1867·2019-08-30 13:09
閱讀 533·2019-08-29 16:05