溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

javascript中編譯原理,作用域,作用域鏈,變量提升,暫時(shí)性死區(qū)是什么

發(fā)布時(shí)間:2020-09-30 16:05:58 來源:億速云 閱讀:189 作者:小新 欄目:web開發(fā)

這篇文章將為大家詳細(xì)講解有關(guān)javascript中編譯原理,作用域,作用域鏈,變量提升,暫時(shí)性死區(qū)是什么,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

JS編譯原理

我們先來看一行代碼

var name='jack';復(fù)制代碼

在我們眼中,這是一行代碼,一個(gè)語句就能搞定的事情呀,但是,在JS的眼里,這句話的代碼應(yīng)該是下面這種方式呈現(xiàn)的

var name;    //編譯階段處理name='jack';    //執(zhí)行階段處理復(fù)制代碼

是不是發(fā)現(xiàn)這和你原本認(rèn)識的JS不太一樣,那是因?yàn)镴S編譯主要分為兩個(gè)階段,編譯階段和執(zhí)行階段,讓我們首先來看下這兩個(gè)階段分別做了那些事情:

  • 編譯階段

    這個(gè)階段的主角就是所謂的編譯器,這個(gè)編譯器會找遍當(dāng)前作用域,看看是不是已經(jīng)存在一個(gè)叫 name 的變量。如果已經(jīng)存在,那么就什么都不做,直接忽略 var name 這個(gè)聲明,繼續(xù)編譯下去;如果沒有,則在當(dāng)前作用域里新增一個(gè)叫 name 的變量。然后,編譯器會為引擎生成運(yùn)行時(shí)所需要的代碼,程序就進(jìn)入了執(zhí)行階段

  • 執(zhí)行階段

    這個(gè)階段的主角就是大家所熟悉的JS引擎啦,JS引擎在運(yùn)行的時(shí)候,也會先找遍當(dāng)前作用域,看看是否有一個(gè)叫 name 的變量,如果有的話,那么剛剛好,直接賦值,如果沒有的話,那就是當(dāng)前作用域沒有,那怎么辦,那就考慮探出頭去,去外面( 父級作用域 )看看有沒有,沒有的話,再去外面查找,一層又一層( 當(dāng)然如果是還有父層的話 ),如果最終還是找不到的話,那么JS引擎也表示無能為力,那就拋個(gè)異常給別人看看吧,表示自己已經(jīng)努力過了。

    上面提到的去外面查找,一層又一層,從當(dāng)前作用域再到父級作用域,再到父級的父級作用域,以此類推,就是所謂的作用域鏈了,就跟鏈條一樣,一節(jié)有一節(jié)往上,是不是形容地可以說是很貼切了。總結(jié)而言就是,作用域套作用域,也就有了所謂的作用域鏈

作用域

  • 定義

    大家都知道,變量最基本的能力就是能夠存儲變量當(dāng)中的值、并且允許我們對這個(gè)變量的值進(jìn)行訪問和修改,而對于變量存儲,訪問的一套規(guī)則,就是所謂的作用域

  • 分類

    • 全局作用域

    在任何函數(shù)外或者代碼塊之外的頂層作用域就是全局作用域,而里面的變量就是全局變量

    var name='jack';   //全局作用域function showName(){    //函數(shù)作用域  console.log(name);}{  name='test';    //塊級作用域}showName();    //test復(fù)制代碼

    可以看到全局變量,無論是在全局作用域,函數(shù)作用,還是塊級作用域中都可以正常訪問

    • 函數(shù)作用域

    在函數(shù)內(nèi)的作用域就是函數(shù)作用域

    function showName(){  var name='jack';    //函數(shù)作用域}showName();   //方法調(diào)用{  console.log(name);  //塊級作用域,Uncaught ReferenceError: name is not defined}console.log(name);  //全局作用域,Uncaught ReferenceError: name is not defined復(fù)制代碼

    可以看到函數(shù)內(nèi)部變量,在全局作用域以及塊級作用域中,都無法訪問,只有在函數(shù)內(nèi)部,才能訪問的到,所以函數(shù)內(nèi)的變量也被稱為局部變量

    • 塊作用域

    ES6 中新出的兩個(gè)新關(guān)鍵字 letconst中,自帶塊級作用域,塊級作用域相當(dāng)于是只在這塊代碼塊中生效,如果它被大括號 {} 所包圍,那么大括號中就是一段代碼塊,代碼塊中使用 letconst 聲明的變量也被稱為局部變量

     {   let name='jack'; } console.log(name);    //Uncaught ReferenceError: name is not defined function showName{   console.log(name); } showName();    //Uncaught ReferenceError: name is not defined復(fù)制代碼

    可以看到塊級作用域中的變量,出了那個(gè)代碼塊,就找不到了

其實(shí)上面的三種情況,結(jié)合JS編譯原理和作用域鏈向外不向內(nèi)查找,思考一下,也不難理解

作用域鏈

回到作用域鏈,其實(shí)在上面已經(jīng)解釋的差不多了,作用域和作用域的嵌套,就產(chǎn)生了作用域鏈,另外要記住的一個(gè)特性就是作用域鏈的查找,向外不向內(nèi),想想探出頭去,而不是看著鍋里,就可以了

變量提升

先來看一段代碼

name='jack';console.log(name);    //jackvar name;復(fù)制代碼

你會發(fā)現(xiàn),這段代碼不會發(fā)生報(bào)錯(cuò),并且能正常地運(yùn)行,結(jié)合上面所說的JS編譯原理,你就能想到,在JS的眼中,它的代碼實(shí)際上是這樣子的,這就是所謂的變量提升,說白了那就是代碼的聲明提到代碼的最前面

var name;name='jack';console.log(name);    //jack復(fù)制代碼

其實(shí)這個(gè)變量提升應(yīng)該是照道理接著編譯原理寫下來的,為什么放到了最后呢,因?yàn)槿绻阃?,正好往上翻一下,重新回溫一遍JS編譯原理

緊接著上面,讓我們來看下不吃變量提升這一套的 letconst ,先來看一段代碼

name='jack';console.log(name)    //Uncaught ReferenceError: Cannot access 'name' before initializationlet name;復(fù)制代碼

黑人問號 ??? ,說好的變量提升呢,記住 letconst 的一個(gè)特點(diǎn),禁用變量提升,這也是 ES6 故意為之的,將生命前不可用做到了強(qiáng)約束,總結(jié)而言,** var 存在變量提升, letconst 不存在變量提升**

既然已經(jīng)提到了 const ,順帶提一下它聲明了以后必須賦值的操作

const name;    //Uncaught SyntaxError: Missing initializer in const declaration復(fù)制代碼

暫時(shí)性死區(qū)

緊接著上面,讓我們來看下什么叫做暫時(shí)性死區(qū),先來看一段代碼

var name='jack';{  name='bob';  let name;    //Uncaught ReferenceError: Cannot access 'name' before initialization}復(fù)制代碼

記住 ES6 中的一個(gè)特性,如果區(qū)塊中存在 letconst 命令,這個(gè)區(qū)塊對這些命令聲明的變量,從一開始就形成了封閉作用域。因?yàn)镴S清楚地感知到了 name 是用 let 聲明在當(dāng)前這個(gè)代碼塊內(nèi)的,所以會給這個(gè)變量 name 加上了暫時(shí)性死區(qū)的限制,它就不往外探出頭了。

那么,如果我們把上面的let name;去掉,程序也將正常運(yùn)行, name 的值也被成功修改為了bob,就是正常地按照作用域鏈的規(guī)則,向外探出頭去了。

關(guān)于javascript中編譯原理,作用域,作用域鏈,變量提升,暫時(shí)性死區(qū)是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI