1. 程式人生 > >JavaScript變數作用域和變數提升

JavaScript變數作用域和變數提升

在看別人程式碼時,發現一個問題,就是一個未在上面宣告或者定義的變數,可以正常使用而且不報錯,我雙擊變數名,編譯器給我把同名的高亮之後,發現這個變數的定義是在使用的下方定義的,網上查詢才得知這是JS變數的一個特性,叫做變數提升,下面,先從最熟知的開始去理解這個變數提升!!

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript變數提升學習</title>
</head>
<body>

<script>
var
a = "HelloWorld!"; console.log(a);
</script> </body> </html>

這是一個基本的變數賦值列印的過程,控制檯輸出結果也是正常的“HelloWorld!”,我們再看下一個:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript變數提升學習</title>
</head>
<body>

<script>
var a = "HelloWorld!"
; (function(){ console.log(a); var a = 'I love you'; })()
</script> </body> </html>

我原先也覺得至少會輸出一個 ‘HelloWorld!’,但是結果卻讓我大錯特錯:!!

這裡就出現了一個JS的語法特徵:變數提升

在理解這個之前,先來理解一下JS變數作用域的問題:

變數作用域

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript變數提升學習</title
>
</head> <body> <script> var abc = 1; console.log(abc); if(1){ var abc = 2; console.log(abc); } console.log(abc); </script> </body> </html>

猜猜輸出結果會是多少:
1,2,1?
1,2,2?
執行結果:
1,2,2
學過C的都知道,區域性變數在函式內定義後,在函式執行完畢就會立刻銷燬,與外部同名的全域性變數不會產生任何影響,是因為在C系語言有塊級作用域,當進入到一個塊時,就像if語句,在這個塊級作用域中會宣告新的變數,這些變數不會影響到外部作用域。但是JavaScript卻不是這樣。

在這段程式碼中,Firebug顯示1,2,2。這是因為JavaScript是函式級作用域(function-level scope)。這和C系語言是完全不同的。塊,就像if語句,並不會建立一個新的作用域。只有函式才會建立新的作用域。

想要解決變數因作用域而對程式的影響時:我們可以這樣:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JavaScript變數提升學習</title>
</head>
<body>

<script>

function foo(){
    var abc = 1;
    if(abc){
        (function(){
            var abc = 2;
        }());
    }
    console.debug(abc);
}

</script>

</body>
</html>

輸出abc時,早已經不存在了:
這裡寫圖片描述
這樣就消除了 變數作用域的困擾。

變數提升

定義三個變數:

(function(){
    var a = 'first';
    var b = 'sconed';
    var c = 'thierd';
})();

實際上它是這樣的:

(function(){
    var a,b,c;
    a = 'first';
    b = 'sconed';
    c = 'thierd';
})();

這時候,就把變數提升了啊!
我們回到前面的第個段程式碼,為什麼顯示undefined?
通過上面的變數提升,我們可以把程式碼寫成:

var a='Hello World'; 
(function(){ 
var a; 
alert(a); 
a='I love you'; 
})() 

所以才會提示undefined。

從這裡,我學習到,我們在寫js 的時候,我們需要把變數放在塊級作用域的頂端,比如上面所舉的例子:var a,b,c;。防止出現意外。