javascript變數聲明提升

來源:互聯網
上載者:User

標籤:

javascript變數聲明提升(hoisting) 

javascript的變數聲明具有hoisting機制,JavaScript引擎在執行的時候,會把所有變數的聲明都提升到當前範圍的最前面。

先看一段代碼

12345 var v = "hello";(function(){  console.log(v);  var v = "world";})();

這段代碼啟動並執行結果是什麼呢?
答案是:undefined
這段代碼說明了兩個問題,
第一,function範圍裡的變數v遮蓋了上層範圍變數v。代碼做少些變動

12345 var v = "hello";if(true){  console.log(v);  var v = "world";}

輸出結果為"hello",說明javascript是沒有塊級範圍的函數是JavaScript中唯一擁有自身範圍的結構。

第二,在function範圍內,變數v的聲明被提升了。所以最初的代碼相當於:

123456 var v = "hello";(function(){  var v; //declaration hoisting  console.log(v);  v = "world";})();

聲明、定義與初始化

聲明宣稱一個名字的存在,定義則為這個名字分配儲存空間,而初始化則是為名字分配的儲存空間賦初值。
用C++來表述這三個概念

123 extern int i;//這是聲明,表明名字i在某處已經存在了int i;//這是聲明並定義名字i,為i分配儲存空間i = 0;//這是初始化名字i,為其賦初值為0

javascript中則是這樣

12 var v;//聲明變數vv = "hello";//(定義並)初始設定變數v

因為javascript為動態語言,其變數並沒有固定的類型,其儲存空間大小會隨初始化與賦值而變化,所以其變數的“定義”就不像傳統的靜態語言一樣了,其定義顯得無關緊要。

聲明提升

當前範圍內的聲明都會提升到範圍的最前面,包括變數和函數的聲明

123456 (function(){  var a = "1";  var f = function(){};  var b = "2";  var c = "3";})();

變數a,f,b,c的聲明會被提升到函數範圍的最前面,類似如下:

1234567 (function(){  var a,f,b,c;  a = "1";  f = function(){};  b = "2";  c = "3";})();

請注意函數運算式並沒有被提升,這也是函數運算式與函式宣告的區別。進一步看二者的區別:

123456789 (function(){  //var f1,function f2(){}; //hoisting,被隱式提升的聲明   f1(); //ReferenceError: f1 is not defined  f2();   var f1 = function(){};  function f2(){}})();

上面代碼中函式宣告f2被提升,所以在前面調用f2是沒問題的。雖然變數f1也被提升,但f1提升後的值為undefined,其真正的初始值是在執行到函數運算式處被賦予的。所以只有聲明是被提升的。

名字解析順序

javascript中一個名字(name)以四種方式進入範圍(scope),其優先順序順序如下:
1、語言內建:所有的範圍中都有 this 和 arguments 關鍵字
2、形式參數:函數的參數在函數範圍中都是有效
3、函式宣告:形如function foo() {}
4、變數聲明:形如var bar;

名字聲明的優先順序如上所示,也就是說如果一個變數的名字與函數的名字相同,那麼函數的名字會覆蓋變數的名字,無論其在代碼中的順序如何。但名字的初始化卻是按其在代碼中書寫的順序進行的,不受以上優先順序的影響。看代碼:

123456789 (function(){    var foo;    console.log(typeof foo); //function         function foo(){}     foo = "foo";    console.log(typeof foo); //string})();

如果形式參數中有多個同名變數,那麼最後一個同名參數會覆蓋其他同名參數,即使最後一個同名參數並沒有定義。

以上的名字解析優先順序存在例外,比如可以覆蓋語言內建的名字arguments。

命名函數運算式

可以像函式宣告一樣為函數運算式指定一個名字,但這並不會使函數運算式成為函式宣告。命名函數運算式的名字不會進入名字空間,也不會被提升。

12345 f();//TypeError: f is not a functionfoo();//ReferenceError: foo is not definedvar f = function foo(){console.log(typeof foo);};f();//functionfoo();//ReferenceError: foo is not defined

命名函數運算式的名字只在該函數的範圍內部有效。

轉自:http://openwares.net/js/javascript_declaration_hoisting.html

javascript變數聲明提升

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.