理解 JavaScript 作用域

上一篇文章中分析了 JS 中的數據類型和變量。這一篇文章將分析作用域,以及回答上一篇文章中變量提升的原因。

什么是作用域

作用域是一套規則,保存著變量,等待被引擎所查找。

var a = 1;
console.log(a);  // => 1
console.log(b);  // => ReferenceError

當打印 a 時,引擎就去作用域中查找 a,找到把結果返回。如果查找失敗,那么就會報錯。

詞法作用域

JS 采用的詞法作用域,也可以說是靜態作用域。簡單來說,詞法作用域是由寫代碼時將變量寫在哪里決定的。

先看一段代碼:

var a = 1;function fn() {var a = 2;return a;
}fn();  // => 2

當執行函數 fn 時,會返回 2,而不是 1。

作用域查找

JS 引擎會進行兩種查找,LHS 和 RHS。怎么理解?L 和 R 可以說代表左和右。什么的左和右?賦值操作的。

這里的賦值操作不一定出現 =,比如參數傳遞也是一個賦值操作。

當變量出現在賦值操作的左邊時,引擎就會對這個變量進行 LHS 查找;當出現在右邊時(這個還可以理解為取得變量的源值),就會進行 RHS 查找。

function foo(a) {console.log(a);
}foo(2);

對于變量 a 來說,引擎會進行兩次查找,1 次 LHS,1 次 RHS。

調用 foo(),并傳入參數 2,這時存在著一個賦值操作即 a = 2,進行一次 LHS 查找。打印 a 時,需要獲取 a 的源值,所以進行一次 RHS 查找。

如果查詢失敗呢?

對于 LHS 來說,給未聲明的賦值就會查詢失敗。

a = 2;

但是我們知道,上面的代碼在非嚴格模式下并不會報錯,而變量 a 會被自動創建。

而對于 RHS 來說,直接使用未聲明的變量就會報 ReferenceError。

console.log(a); // => ReferenceError

另外,RHS 雖然查詢成功,但是卻對查詢結果進行非法操作,就會報 TypeError。

var foo = 1;
foo(); // => TypeError

作用域鏈

前面說,作用域是根據名稱查找變量的一套規則。而在實際情況中,經常出現多個作用域嵌套的情況。

function foo(a) {console.log(a + b);
}
var b = 2;
foo(2); // => 4

當引擎對 b 進行 RHS 查找時,在當前作用域無法找到,引擎就會在外層作用域中查找,直到找到這個變量,或者直到抵達最外層作用域(全局作用域)為止。

LHS 查找也是如此。

把這樣一層一層嵌套的作用域,叫做作用域鏈。

函數作用域

函數作用域是指,屬于這個函數的全部變量都可以在這個函數的范圍內使用及復用。

function foo() {var a = 1;
}console.log(a); // => ReferenceError

也就是說,函數外部將無法訪問函數內部的變量。

但是這卻是非常有用的。我們可以利用函數隱藏內部實現,使其外部無法訪問、修改等。

立即執行函數表達式

利用函數作用域,可以將外部作用域無法訪問的內容包裝起來。但是,帶來了額外的一個問題,函數名本身“污染”了所在的作用域。

這時,就提出了 IIFE(立即執行函數表達式)。

(function foo() {// ...
}());

即包裝了內部函數,又避免了引入函數名。因為這個函數名無法被外部作用域所訪問。

IIFE 的進階用法是給其傳入參數:

(function fn(global) {// ...
})(window);

這樣的好處是可以縮短查詢時的作用域鏈。

塊作用域

ES6,通過 let 和 const 引入了塊作用域。

if (true) {let a = 1;
}
console.log(a); // => ReferenceError

變量提升

上一篇文章中中提到了變量提升。

在 JS 中,var a = 1; 這行代碼其實會被看成 var aa = 2,并在兩個階段去執行。

在編譯階段,執行聲明操作;在執行階段,執行賦值操作。

所有的變量聲明都會被提升到作用域的頂部,這個過程叫做“提升”。

函數聲明也會發生提升,并且函數聲明會先于變量提升:

var foo = 1;
function foo () {}typeof foo; // => 'number'

注意,只有函數聲明會被提升,而函數表達式不會被提升。

var foo = 1;
var foo = function () {}typeof foo; // => 'function'

小結

這篇文章梳理了 JavaScript 中作用域的基本知識。

接下來會介紹執行上下文和閉包這兩個概念,它們與作用域息息相關。

關于

這是我的公眾號,記錄著我的前端博客,沒事兒也分享一些電影、書籍。

歡迎一起交流學習。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/537426.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/537426.shtml
英文地址,請注明出處:http://en.pswp.cn/news/537426.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mysql行求和

SELECT 列1 列2 列3 …… 列N AS Total FROM 表 SELECT sum(列1 列2 列3 …… 列N) AS Total FROM 表 轉載于:https://www.cnblogs.com/weilovehua/p/10024624.html

python安裝后在哪里找_python安裝后的目錄在哪里

從官網下載python的安裝包,安裝過程中可選擇裝在C盤或D盤或者其他的磁盤。 如果忘記了安裝在哪里,可以在命令行中使用以下命令 where python 會顯示python的絕對路徑 C:\Users\Administrator>where python C:\Users\Administrator\AppData\Local\Prog…

Axure原型設計導出到PDF文件

Axure 沒有直接導出PDF文件的功能,可以通過Axure 的打印功能,選擇PDF打印機,以間接的方式將原型設計導出到pdf文件里。 操作步驟 以Axure9為例 打印 Axure9---文件---打印 不要母版 預覽 預覽下效果,看下是否有不必要的內容 …

izoak028

離散數學 (自考) 【自考】計算機網絡原理精講(2018版)轉載于:https://www.cnblogs.com/qianyindichang2/p/10025538.html

Word查找替換詳細用法及通配符一覽表

使用通配符 要查找“?”或者“*”&#xff0c;可輸入“\?”和“\*”&#xff0c;\1\2\3依次匹配數對括號內容 查找(a)12(b) 替換\2XY\1 結果&#xff1a;bXYa ([.0-9]) [MG]B 匹配文件大小&#xff0c; 例1: 201 MB ,例2: 2.51 GB <(e*r)> 匹配“…

python pca降維_機器學習的降維打擊

文章發布于公號【數智物語】 (ID&#xff1a;decision_engine)&#xff0c;關注公號不錯過每一篇干貨。來源 | SAMshare(id:SAMshare)作者 | samshare"本次主要講解的內容就是特征降維&#xff0c;主要涉及PCA以及一些常見分析方法。"01Index一&#xff0c;PCA降維算…

什么樣的項目是成功的?

項目成功的標準是什么&#xff1f; 項目范圍控制住&#xff0c;成本沒超標&#xff0c;質量達標&#xff0c;進度按計劃&#xff0c;順利驗收。做到這些就是項目成功了嗎&#xff1f; 答案顯然是不一定&#xff01;&#xff01;! 有多少項目的成本、進度、目標都能夠嚴格按照…

ng-notadd 0.10.1,基于 Angular7 和 material2 的中后臺解決方案

更新內容修復 scss左側導航欄美化修復導航欄 2px 間隔問題技術棧TypescriptAngularMaterial2rxjsGraphql相關鏈接項目地址DEMOng-notadd-mock-serverQuick startgit clone https://github.com/notadd/ng-notadd.gitcd ng-notaddnpm installnpm start# or use ng cling serve復制…

python需要什么包裝_python學習之包裝與授權

實現授權的關鍵點就是覆蓋__getattr__()方法&#xff0c;在代碼中包含一個對getattr()內建函數的調用。 特別調用getattr()以得到默認對象屬性&#xff08;數據屬性或者方法&#xff09;并返回它以便訪問或調用。 特殊方法__getattr__()的工作方式是&#xff0c;當搜索一個屬性…

參加技術培訓前的輔導,選得對,學得好

最近幾年&#xff0c;每年都會有人問我培訓班的事情&#xff0c;我也有培訓班經歷&#xff0c;在軟件行業工作了十多年&#xff0c;每次解答培訓班的咨詢我都很認真&#xff0c;也很高興能幫到他人。 決定通過專欄的形式解答培訓班常見問題&#xff0c;我把專欄取名“技術培訓…

[算法]淺談求n范圍以內的質數(素數)

汗顏&#xff0c;數學符號表達今天才學會呀-_-# 下面是百度百科對質數的定義 質數&#xff08;prime number&#xff09;又稱素數&#xff0c;有無限個。質數定義為在大于1的自然數中&#xff0c;除了1和它本身以外不再有其他因數。求質數的方法自然不少&#xff0c;但主要還是…

進入IT行業,要不要參加培訓班?

IT行業介紹 考慮培訓班無非是要入行,那IT行業好不好?IT行業當然好,看看培訓班的數量就知道了。現在房產行業好賺錢,每個小區門口好幾家中介門店,相同品牌的可能不止1家。不用去看網上的軟文,也不用去問百度,看市場的反應,這是真實的反饋。培訓班越來越多,課程越來越多…

python commands_Windows環境下使用python的commands.getstatusoutput

windows調用系統或其他腳本的&#xff0c;常用的是os.popen&#xff0c;次命令本身并不返回執行后的狀態&#xff0c;無法用于后續的判斷&#xff0c;故嘗試Unix下的commands.getstatusoutput&#xff0c;發現在windows下并不能正常使用&#xff0c;如下&#xff1a; >>&…

Kubernetes在上汽集團云平臺及AI方面的應用

2019獨角獸企業重金招聘Python工程師標準>>> 帆一尚行成立于2015年&#xff0c;是上汽集團的全資子公司&#xff0c;建設有上海、南京、鄭州&#xff08;在建&#xff09;三個數據中心&#xff0c;擁有超過4000臺物理服務器&#xff0c;10PB的數據存儲&#xff0c;總…

我的Java培訓經歷

此文講述我的Java開發培訓經歷&#xff0c;來解答關心的培訓費、培訓節奏、就業等問題。 我在2010年參加達內Java培訓&#xff0c;如今再回首那段時光&#xff0c;雖然辛苦&#xff0c;但很值得&#xff01;&#xff08;后悔參加培訓班&#xff0c;大部分原因是沖動&#xff0…

python跨函數調用變量_對python中不同模塊(函數、類、變量)的調用詳解

首先&#xff0c;先介紹兩種引入模塊的方法。 法一&#xff1a;將整個文件引入 import 文件名 文件名.函數名( ) / 文件名.類名 通過這個方法可以運行另外一個文件里的函數 法二&#xff1a;只引入某個文件中一個類/函數/變量 需要從某個文件中引入多個函數或變量時&#xff0c…

軟件培訓技術選哪個?

要培訓了,培訓技術怎么選? 技術需慎重選 女怕嫁錯郎,男怕入錯行。后悔參加培訓班,因為技術沒選好的占比很高。 技術沒選好會有什么影響? 近的影響是就業!遠的影響是發展! 對于程序員來說,技術就是立身之本,需要慎重選擇! 我在《要不要參加培訓班?》文章中介紹…

django安裝_技術大牛詳解:Django框架之環境安裝

黑馬程序員視頻庫播妞微信號&#xff1a;boniu236傳智播客旗下互聯網資訊、學習資源免費分享平臺虛擬環境安裝:開發中問題&#xff1a;如何在同一臺主機中&#xff0c;要開發多個不同的項目&#xff0c;而且需要用到同一個包的不同版本&#xff1f;嘗試分析&#xff1a;在開發過…

安裝 Alibaba Cloud Toolkit

IntelliJ IDEA版 JetBrains 插件市場下載 Eclipse 版 Eclipse 插件市場倉庫下載 (推薦)URL 地址在線安裝Maven 版 在 POM 文件中依賴 PyCharm、PhpStorm、RubyMine 和 WebStorm 版 公測中官網https://toolkit.aliyun.com 交流群&#xff08;釘釘&#xff09; 交流群&#xff08…

軟件Java前端大數據培訓機構怎么選?

先看這篇文章《要不要參加培訓班》。 選技術就像選另一半,那選培訓機構就是選另一半的家庭。另一半家庭好與不好,與婚后幸福生活息息相關。 選培訓機構的幾個維度: 1.成立時間 2.專業性 3.市場普及率 成立時間 成立久的不一定好,比如北大某鳥 成立不足3年的,不要選…