中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

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

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

javascript中編譯原理,作用域,作用域鏈,變量提升,暫時性死區是什么

發布時間:2020-09-30 16:05:58 來源:億速云 閱讀:199 作者:小新 欄目:web開發

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

JS編譯原理

我們先來看一行代碼

var name='jack';復制代碼

在我們眼中,這是一行代碼,一個語句就能搞定的事情呀,但是,在JS的眼里,這句話的代碼應該是下面這種方式呈現的

var name;    //編譯階段處理name='jack';    //執行階段處理復制代碼

是不是發現這和你原本認識的JS不太一樣,那是因為JS編譯主要分為兩個階段,編譯階段和執行階段,讓我們首先來看下這兩個階段分別做了那些事情:

  • 編譯階段

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

  • 執行階段

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

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

作用域

  • 定義

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

  • 分類

    • 全局作用域

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

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

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

    • 函數作用域

    在函數內的作用域就是函數作用域

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

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

    • 塊作用域

    ES6 中新出的兩個新關鍵字 letconst中,自帶塊級作用域,塊級作用域相當于是只在這塊代碼塊中生效,如果它被大括號 {} 所包圍,那么大括號中就是一段代碼塊,代碼塊中使用 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復制代碼

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

其實上面的三種情況,結合JS編譯原理和作用域鏈向外不向內查找,思考一下,也不難理解

作用域鏈

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

變量提升

先來看一段代碼

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

你會發現,這段代碼不會發生報錯,并且能正常地運行,結合上面所說的JS編譯原理,你就能想到,在JS的眼中,它的代碼實際上是這樣子的,這就是所謂的變量提升,說白了那就是代碼的聲明提到代碼的最前面

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

其實這個變量提升應該是照道理接著編譯原理寫下來的,為什么放到了最后呢,因為如果你忘了,正好往上翻一下,重新回溫一遍JS編譯原理

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

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

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

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

const name;    //Uncaught SyntaxError: Missing initializer in const declaration復制代碼

暫時性死區

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

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

記住 ES6 中的一個特性,如果區塊中存在 letconst 命令,這個區塊對這些命令聲明的變量,從一開始就形成了封閉作用域。因為JS清楚地感知到了 name 是用 let 聲明在當前這個代碼塊內的,所以會給這個變量 name 加上了暫時性死區的限制,它就不往外探出頭了。

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

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

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

灵寿县| 和静县| 龙江县| 洛南县| 龙井市| 佛坪县| 冕宁县| 茶陵县| 乌拉特前旗| 云梦县| 文成县| 涿州市| 湘阴县| 东乌珠穆沁旗| 江源县| 巫山县| 浙江省| 叙永县| 梨树县| 十堰市| 甘德县| 嘉祥县| 安庆市| 抚州市| 威海市| 黑河市| 阳信县| 将乐县| 本溪市| 陈巴尔虎旗| 吉林省| 浑源县| 城固县| 依兰县| 新龙县| 武平县| 长阳| 河南省| 星座| 上犹县| 纳雍县|