国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript 作用域不完全指北

coordinate35 / 2351人閱讀

摘要:一旦到達頂層全局作用域,可能找到,也可能沒有找到,查找過程都必須停止。當引擎執行查詢時,如果查詢在所有嵌套的作用域中遍尋不到所需的變量,引擎就會拋出異常。代表作用域判別失敗相關,而則代表作用域判別成功了,但是對結果的操作是非法或不合理的。

什么是作用域

對于幾乎所有編程語言,最基本的功能之一就是能夠存儲變量的值,并且能在之后對這個值進行訪問和修改。這樣就會帶來幾個問題,這些變量存儲在哪里?程序在需要的時候又是如何找到它們的?要解決這些問題,就需要引入一套規則來存儲變量和訪問變量,這套規則就是作用域。

理解作用域

在剛開始接觸 JavaScript 這門語言時,肯定會經常接觸到?JavaScript 是動態語言,?是解釋執行的,但事實上?JavaScript 是一門編譯語言。只不過和 Java、C# 這些傳統意義上的編譯語言不同,JavaScript 的編譯過程不是發生在構建之前的。大部分情況下,JavaScript 的編譯過程發生在代碼執行前的很短時間內。也就是說?JavaScript 代碼在執行前都要進行編譯。

為了更好地理解作用域,我們需要明確下面幾個概念

引擎

從頭到尾負責整個 JavaScript 程序的編譯及執行過程

編譯器

負責語法分析及代碼生成等臟活累活

作用域

負責收集并維護由所有聲明的標識符(變量) 組成的一系列查詢, 并實施一套非常嚴格的規則, 確定當前執行的代碼對這些標識符的訪問權限。

下面我們從引擎、編譯器和作用域的角度,分析 var a = 2?這條聲明語句,看看它們是如何協同完成工作的

遇到 var a, 編譯器會詢問作用域是否已經有一個該名稱的變量存在于同一個作用域的集合中。 如果是, 編譯器會忽略該聲明, 繼續進行編譯; 否則它會要求作用域在當前作用域的集合中聲明一個新的變量, 并命名為a。

接下來編譯器會為引擎生成運行時所需的代碼, 這些代碼被用來處理 a = 2 這個賦值操作。 引擎運行時會首先詢問作用域, 在當前的作用域集合中是否存在一個叫作 a 的變量。 如果是, 引擎就會使用這個變量; 如果否, 引擎會繼續查找該變量。如果引擎最終找到了 a 變量, 就會將 2 賦值給它。 否則引擎就會舉手示意并拋出一個異常!

簡單來說,變量的賦值操作會執行兩個動作, 首先編譯器會在當前作用域中聲明一個變量(如果之前沒有聲明過), 然后在運行時引擎會在作用域中查找該變量, 如果能夠找到就會對它賦值,否則就會并拋出一個異常。

作用域嵌套

我們知道引擎查找變量的過程在作用域中進行的,而這個過程通常會涉及多個作用域。

當一個塊或函數嵌套在另一個塊或函數中時, 就發生了作用域的嵌套。 因此, 在當前作用域中無法找到某個變量時, 引擎就會在外層嵌套的作用域中繼續查找, 直到找到該變量,或抵達最外層的作用域(也就是全局作用域) 為止。

為了便于理解,可以將作用域嵌套比喻成一棟高樓,我們從一樓(當前作用域)開始查找,如果沒有找到,就會前往上一個樓層繼續查找,以此類推。一旦到達頂層(全局作用域),可能找到,也可能沒有找到,查找過程都必須停止。

LHS查詢和RHS查詢

繼續上文的示例,引擎在執行編譯器生成的代碼時,會通過查找變量 a 來判斷它是否已經聲明過。查找的過程由作用域進行協助, 但是引擎執行怎樣的查找, 會影響最終的查找結果。查找過程分為兩類:LHS查詢和RHS查詢。其實很簡單,當變量出現在賦值操作的左側時進行 LHS 查詢, 出現在右側時進行 RHS 查詢。
更準確一點的講,?RHS?查詢是查找某個變量的值,而?LHS?查詢是查找變量的容器本身,從而可以對其賦值。如下面的示例:

var a = 2; // a: LHS查詢
var b = 3; // b: LHS查詢
a = b; //a: LHS查詢 b:RHS查詢

為什么區分 LHS 和 RHS 是一件重要的事情?

因為在變量還沒有聲明(在任何作用域中都無法找到該變量) 的情況下, ?LHS?和?RHS兩種查詢的行為是不一樣的

1.當引擎執行?RHS?查詢時,如果 RHS 查詢在所有嵌套的作用域中遍尋不到所需的變量, 引擎就會拋出 ReferenceError異常。?

console.log(a); //ReferenceError: a is not defined

2.當引擎執行 LHS 查詢時, 如果在頂層(全局作用域) 中也無法找到目標變量,全局作用域中就會創建一個具有該名稱的變量, 并將其返還給引擎, 前提是程序運行在非“嚴格模式” 下。如果在“嚴格模式”下,引擎也會拋出?ReferenceError異常。

//非嚴格模式
var a =2;
b = a;
console.log(b); //2
//嚴格模式
"use strict";
var a =2;
b = a;
console.log(b); //ReferenceError: b is not defined

另外,如果 RHS 查詢找到了一個變量, 但是你嘗試對這個變量的值進行不合理的操作,比如試圖對一個非函數類型的值進行函數調用, 或著引用 null 或 undefined 類型的值中的屬性, 那么引擎會拋出另外一種類型的異常, 叫作TypeError。

ReferenceError 代表作用域判別失敗相關, 而 TypeError 則代表作用域判別成功了, 但是對結果的操作是非法或不合理的。

參考

《你不知道的JavaScript》

微信公眾號:

聲明:本文為博主學習感悟總結,水平有限,如果不當,歡迎指正。轉載與引用請注明作者及出處。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/104559.html

相關文章

  • styled-components 中文文檔翻譯及不完全指北

    摘要:前言官方文檔地址中文文檔地址是一個的第三方庫,是的優秀實踐。初次了解是在讀林昊翻譯的設計模式與最佳實踐一書時。能力所限,已翻譯部分可能仍有字詞錯誤或語句不通順的地方,歡迎有能力的同學幫助糾正。就是其中的佼佼者。 前言 官方文檔地址: https://www.styled-components.com/ 中文文檔地址:https://github.com/hengg/styled-com...

    Vicky 評論0 收藏0
  • styled-components 中文文檔翻譯及不完全指北

    摘要:前言官方文檔地址中文文檔地址是一個的第三方庫,是的優秀實踐。初次了解是在讀林昊翻譯的設計模式與最佳實踐一書時。能力所限,已翻譯部分可能仍有字詞錯誤或語句不通順的地方,歡迎有能力的同學幫助糾正。就是其中的佼佼者。 前言 官方文檔地址: https://www.styled-components.com/ 中文文檔地址:https://github.com/hengg/styled-com...

    OnlyLing 評論0 收藏0
  • ES6指北【5】——展開語法(spread syntax)

    摘要:我們先來看一看的官方定義展開語法可以在函數調用數組構造時將數組表達式或者在語法層面展開還可以在構造字面量對象時將對象表達式按的方式展開。 我們先來看一看MDN的官方定義 展開語法(Spread syntax), 可以在函數調用/數組構造時, 將數組表達式或者string在語法層面展開;還可以在構造字面量對象時, 將對象表達式按key-value的方式展開。(譯者注: 字面量一般指 [1...

    ZoomQuiet 評論0 收藏0
  • ES6指北【6】——詳談解構賦值【附贈練習題】

    摘要:指北詳談解構賦值附贈練習題一何謂解構賦值基本概念首先我們看一下給的定義解構賦值語法是一個表達式,這使得可以將值從數組或屬性從對象提取到不同的變量中從定義中,我們可以發現解構賦值的作用是對變量進行賦值主要通過兩個方面實現這個作用數組將數組中的 ES6指北【6】——詳談解構賦值【附贈練習題】 一、何謂解構賦值? 1. 基本概念 首先我們看一下MDN給的定義 解構賦值語法是一個 Javasc...

    sorra 評論0 收藏0
  • ES6指北【2】—— 箭頭函數

    摘要:箭頭函數基本語法函數語法具名函數匿名函數三句話第一句話聲明第二句話聲明匿名函數第三句話把匿名函數賦值給箭頭函數語法特點只能做賦值,不能做聲明第一種寫法完全寫法不省略參數個數,不省略函數體花括號參數個數函數體內語句個數第二種寫法省略參數括號參 1.箭頭函數基本語法 1.1 ES3 函數語法 // 具名函數 function xxx(arg1, arg2) { console.lo...

    DobbyKim 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<