亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Javascript中作用域的詳細介紹

 更新時間:2016年10月06日 08:54:30   作者:睡在我下鋪的上鋪的胖子  
這篇文章主要為大家詳細介紹了Javascript中的作用域,具有一定的參考價值,感興趣的朋友可以參考一下

1、編譯原理

在傳統(tǒng)編譯語言的流程中,程序中的一段代碼執(zhí)行前會經(jīng)歷三個步驟。統(tǒng)稱為“編譯”。

詞法分析

  將代碼字符串分解成有意義的代碼塊,這些代碼塊稱為詞法單元。例如:在js中,var a = 2;。這段程序通常被拆分為以下詞法單元。var、a、2、;。至于空格是否會被當(dāng)成詞法單元,取決于空格在這門語言中是否有意思。
語法分析
  將詞法單元流(數(shù)組)轉(zhuǎn)換為“抽象語法樹”(AST,Abstract Syntax Tree。編譯原理課程中提到過)。
代碼生成
  將AST轉(zhuǎn)換為可執(zhí)行代碼。與語言,平臺有關(guān)(java跨平臺)。簡單來說:var a = 2;的AST被轉(zhuǎn)換成一組機器指令,用來創(chuàng)建一個a的變量(分配內(nèi)存等),并將2存儲在a中。   

  而對于Javascript而言,盡管通常它被歸類為“動態(tài)”或“解釋執(zhí)行”語言,但實際上它是一門編譯語言。所不同的是,在它編譯時引擎要執(zhí)行更復(fù)雜的操作過程。   
  首先,Javascript引擎不會有大量的(向其他編譯器那么多的)時間來進行優(yōu)化,因為與其他語言不同,它的編譯過程不是在構(gòu)建之前的。   
  對于Javascript而言,大部分編譯發(fā)生在代碼執(zhí)行前的幾微秒(甚至更短)。所以引擎會用盡各種方法(比如JIT)來保證性能最佳。   
  簡單的說,任何Js代碼在執(zhí)行前都要編譯(幾微秒前)。因此,在執(zhí)行var a = 2;這段代碼前,引擎會先編譯,然后做好執(zhí)行它的準(zhǔn)備(加入到代碼隊列)。通常是馬上執(zhí)行。

2、理解作用域

引擎
  負責(zé)整個編譯以及執(zhí)行過程。
編譯器
  引擎的好朋友之一,負責(zé)語法分析和代碼生成等臟活累活。
作用域
  引擎的另一個好朋友,負責(zé)收集和維護所有變量,并實施一套非常嚴格的規(guī)則,以保證當(dāng)前代碼(作用域)對變量的訪問權(quán)限。

  對于var a = 2;,它不僅僅是一句簡單的聲明。聲明它有兩個過程。編譯時:編譯器進行相關(guān)操作。執(zhí)行時,Js引擎進行相關(guān)操作。

var a,編譯器會在當(dāng)前作用域查找是否有a這個變量。如果有,則編譯器忽略此聲明。否則,在當(dāng)前作用域創(chuàng)建一個a變量(分配內(nèi)存)。

a = 2,接下來編譯器(語法分析,代碼生成…)生成運行時所需的代碼用來處理這個賦值操作。具體的賦值操作由Js引擎負責(zé)。Js引擎會在當(dāng)前作用域查找a這個變量,如果找到,就進行賦值操作。否則,在父級作用域查找(作用域嵌套),直至全局作用域。如果找到,進行賦值操作。找不到拋出異常。

在查找作用域的過程中,會涉及到LHS查詢和RHS查詢。它們分別代表賦值操作的目標(biāo)和賦值操作的源頭。不僅僅是賦值操作,更有函數(shù)賦值操作等等。比如:

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

  最后一行foo()函數(shù)的調(diào)用需要對foo()本身進行RHS查詢。在全局作用域中找到了foo的聲明。并且()意味著要把foo當(dāng)做一個函數(shù)執(zhí)行,所以foo最好是一個函數(shù),否則會報錯。   

  還有一個容易忽視的細節(jié)。在把2作為實參傳入到foo的形參時,會有一個隱式的a=2操作。a是賦值操作的源頭,2是賦值操作的目標(biāo)。所以這里對a進行了一次LHS查詢。由于在編譯過程中在當(dāng)前作用域(函數(shù)作用域)將a聲明為foo的一個形參了,所以可以找到。   

  然后就是console.log(a);,console本身也需要一個LHS查詢,它是在window下面的內(nèi)置對象,所以可以找到。然后對a進行RHS查詢。幸運的是,在將2賦值給函數(shù)形參a的時候,a已經(jīng)聲明并賦值了。所以這個RHS是可以進行的。

3、作用域嵌套

  在之前我們說過,作用域負責(zé)收集和維護所有變量,并實施一套非常嚴格的規(guī)則,以保證當(dāng)前代碼(作用域)對變量的訪問權(quán)限??紤]以下代碼:

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

  我們只考慮這里對b的RHS引用。Js引擎開始試圖在foo函數(shù)作用域查找b變量,但是并沒有找到。于是,Js引擎就會突破當(dāng)前限制,去外層作用域查找。哎呀,找到了!于是就對b進行RHS引用成功了。當(dāng)然呢,要是沒找到的話,Js引擎也不會放棄,會繼續(xù)往外層作用域查找,直到找到全局作用域。然后遵循的規(guī)則參照a=2賦值那塊。

4、異常

  在一個變量還沒有聲明(任何作用域都無法查到)的情況下,LHS和RHS查詢失敗后的操作是不一樣的??梢灶A(yù)料,RHS查詢失敗會拋出一個異常,那么LHS查詢失敗呢?

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

  第一次對b進行RHS查詢時,在任何作用域無法找到該變量的聲明。那么有小伙伴就疑惑了,b=a呢?不是對b的聲明嗎?答案是:是。這里確實是對b的聲明。
   但在對作用域查找的過程中,只會向上查找聲明(涉及到聲明提升)。由于這里b是在console.log()后面定義的。所以是失敗的,拋出ReferenceError異常。值得注意的是,ReferenceError是非常重要的異常類型。再考慮下述代碼:

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

  這里呢,第一次對b進行的是LHS查詢。如果在頂層(全局)作用域也無法查到foo的話,那么Js引擎就會很熱心的幫你在全局作用域創(chuàng)建一個b變量,前提是在非“嚴格模式”下,在一個作用域內(nèi)加上代碼“use strict”,表明使用嚴格模式。在嚴格模式下,LHS查詢失敗時,并不會創(chuàng)建一個全局變量,而是拋出同RHS查詢失敗時類似的ReferenceError異常。   
  接下來,加入你找到了這個變量,但是你試圖對這個變量進行不合理的操作。如:對一個非函數(shù)類型的變量進行()函數(shù)調(diào)用、對null或undefined類型的值進行訪問,那么引擎會拋出另一種類型的異常,叫做TypeError。   
  總之,RefercenError同作用域判別失敗相關(guān),而TypeError表示作用域判別成功,但是對結(jié)果的操作是不合法的。

5、小結(jié)

  作用域是一套規(guī)則,規(guī)定在何處以及如何查找變量(加上之前說的,重要的事情說三遍)。如果查找的目的是賦值,就是進行LHS查詢。如果目的是獲取變量的值,就會進行RHS查詢。   
  Js引擎會在代碼執(zhí)行前對其進行編譯。var a = 2;,這樣的操作會被分成兩個步驟。   
  1.編譯時, 編譯器聲明a變量,即var a。
  2. 運行時,對a變量進行賦值。a=2。
  LHS查詢和RHS查詢失敗會進行不同的操作。RHS查詢失敗會拋出ReferenceError異常。LHS查詢失敗會在全局作用域創(chuàng)建變量(非嚴格模式),在嚴格模式下拋出ReferenceError異常。

以上就是本文的全部內(nèi)容,希望對大家有所幫助,希望大家繼續(xù)關(guān)注腳本之家的最新內(nèi)容。

相關(guān)文章

  • JavaScript驗證API的使用

    JavaScript驗證API的使用

    本文主要介紹了JavaScript驗證API的使用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • javascript 正則表達式相關(guān)應(yīng)介紹

    javascript 正則表達式相關(guān)應(yīng)介紹

    javascript 中幾個與正則表達式相關(guān)的應(yīng)用,本文將詳細介紹,需要的朋友可以參考下
    2012-11-11
  • c#程序員對TypeScript的認識過程

    c#程序員對TypeScript的認識過程

    本文向大家詳細展示了從C#程序員的視角學(xué)習(xí)TypeScript的過程,主要是針對這兩種語言的異同進行了簡單的對比學(xué)習(xí),希望對大家能夠有所幫助。
    2015-06-06
  • js將控件隱藏的方法及display屬性介紹

    js將控件隱藏的方法及display屬性介紹

    這篇文章主要介紹了,js中將控件隱藏的方法,以及display的屬性,有需要的朋友可以參考一下
    2013-07-07
  • web 頁面分頁打印的實現(xiàn)

    web 頁面分頁打印的實現(xiàn)

    網(wǎng)上找的,經(jīng)我整理添加demo如下
    2009-06-06
  • JavaScript實現(xiàn)打地鼠小游戲

    JavaScript實現(xiàn)打地鼠小游戲

    這篇文章主要為大家詳細介紹了JavaScript實現(xiàn)打地鼠小游戲的相關(guān)代碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • JavaScript打開客戶端exe文件的代碼

    JavaScript打開客戶端exe文件的代碼

    可以運行客戶端exe文件的代碼
    2008-10-10
  • Bootstrap table的使用方法

    Bootstrap table的使用方法

    這篇文章主要為大家詳細解析了JS組件Bootstrap Table使用方法,具有一定的實用性和參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • 5個讓你眼前一亮的JavaScript裝飾器技巧

    5個讓你眼前一亮的JavaScript裝飾器技巧

    JavaScript?裝飾器是一種特殊的功能,允許在不修改源代碼的情況下動態(tài)修改類和函數(shù)的行為,本文將介紹五個讓你眼前一亮的裝飾器技巧,包括裝飾函數(shù)參數(shù)、裝飾類屬性、裝飾函數(shù)返回值和裝飾函數(shù)調(diào)用,需要的朋友可以參考下
    2023-06-06
  • 微信小程序?qū)崿F(xiàn)皮膚功能(夜間模式)

    微信小程序?qū)崿F(xiàn)皮膚功能(夜間模式)

    這篇文章主要給大家介紹了關(guān)于利用微信小程序?qū)崿F(xiàn)皮膚功能,也就是實現(xiàn)夜間模式的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。
    2017-06-06

最新評論