js變數範圍--變數提升

來源:互聯網
上載者:User

標籤:color   var   對象   enc   strong   undefined   全域   not   定義   

1、JS範圍

在ES5中,js只有兩種形式的範圍:全域範圍和函數範圍,在ES6中,新增了一個塊級範圍(最近的大括弧涵蓋的範圍),但是僅限於let方式申明的變數。

2、變數聲明

1 var x;      //變數聲明2 var x=1;    //變數聲明並賦值3 x = 1;    // 定義全域變數並賦值

3、函式宣告

function fn(){};     //函式宣告並定義var fn = function(){};    // 實際上是定義了一個局部變數fn和一個匿名函數,然後把這個匿名函數賦值給了fn

4、變數提升

var tmp = new Date();function fn(){    console.log(tmp);  //Wed Jul 12 2017 22:11:56 GMT+0800 (中國標準時間)}
fn();

a情形

var tmp = new Date();function fn(){    console.log(tmp);    //undefined    if(false){        var tmp = ‘hello‘;    }}fn();

b情形

var tmp = new Date();function fn(){    console.log(tmp);    //undefined    if(true){        var tmp = ‘hello‘;    }}fn();

c情形

從上面可以看到,b情形和c情形為什麼不同於a情形,就是因為變數提升了(ps: c情形不同於b情形的是判斷條件為true,但是這裡不是看代碼有沒有被執行,是看變數有沒有被定義)。fn函數裡面定義了同名變數tmp,無論在函數的任何位置定義tmp變數,它都將被提升到函數的最頂部。等同於下面情形:

var tmp = new Date();console.log(tmp);function fn(){        var tmp;    console.log(tmp);    //undefined    if(false){        var tmp = ‘hello‘;    }}fn();

這裡需要說明的是,雖然所有的申明(包括ES5的var、function,和ES6的function *、let、const、class)都會被提升,但是var、function、function *和let、const、class的的提升卻並不相同!具體原因可以看這裡的說明(大體的意思是雖然let,const,class也被提升了,但是卻並不會被初始化,這時候去訪問他們則會報ReferenceError異常,他們需要到語句執行的時候才會被初始化,而在被初始化之前的狀態叫做temporal dead zone)。

因為這樣的原因,推薦的做法是在申明變數的時候,將所用的變數都寫在範圍(全域範圍或函數範圍)的最頂上,這樣代碼看起來就會更清晰,更容易看出來那個變數是來自函數範圍的,哪個又是來自範圍鏈。

5、重複聲明

var x = 1;console.log(x);if(true){    var x = 2;    console.log(x);}console.log(x);

上面的輸出其實是:1 2 2。雖然看起來裡面x申明了兩次,但上面說了,js的var變數只有全域範圍和函數範圍兩種,且申明會被提升,因此實際上x只會在最頂上開始的地方申明一次,var x=2的申明會被忽略,僅用於賦值。也就是說上面的代碼實際上跟下面是一致的:

var x = 1;console.log(x);if(true){    x = 2;    console.log(x);}console.log(x);

6、函數和變數同時提升的問題

console.log(fn);function fn(){};var fn = ‘string‘;

上面的輸出結果其實是: function fn(){} ,也就是函數內容。

console.log(fn);var fn = function fn(){};var fn = ‘string‘;

這時輸出結果就是undefined,知道上面的聲明提升的道理就不難理解了。

總結:

要徹底理解JS的範圍和Hoisting,只要記住以下三點即可:

      1、所有申明都會被提升到範圍的最頂上

      2、同一個變數申明只進行一次,並且因此其他申明都會被忽略

      3、函式宣告的優先順序優於變數申明,且函式宣告會連帶定義一起被提升

注意:

通過with語句,可以臨時改變運行期內容相關的範圍鏈,此時的對非var定義的變數進行訪問,會首先訪問with中對象的屬性,然後才會向上順著範圍鏈向上檢查該屬性。

js變數範圍--變數提升

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.