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?
執行結果:
學過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;。防止出現意外。