前言
Javascript中的變量定義方式有以下三種方式:
1、直接定義變量,var與let均不寫;
a = 10;
2、使用var關鍵字定義變量
var a = 10;
3、使用let關鍵字定義變量
let a = 10;
這三種方式有什么區別呢?
JavaScript全局變量和局部變量又是什么呢?
可以帶着這兩個問題往下看。
變量的作用域
變量是有作用域的,大多數語言中的變量的作用域都有全局變量和局部變量之分。
首先我們建立一個文件test1.html,從中輸入以下代碼:
<script type="text/javascript">
//在函數外使用var關鍵字聲明變量test_var1
var test_var1 = "變量1";
//定義函數testFun
function testFun(){
//在函數中定義變量沒加任何關鍵字的變量test_var2
test_var2 = "變量2";
//函數內使用var關鍵字定義的test_var3
var test_var3 = "變量3";
}
//函數執行
testFun();
alert(test_var1 + "\n" + test_var2);
alert(test_var3);
</script>
在瀏覽器打開我們的html頁面,可以看到只彈出了一個彈窗:

第二個彈窗為什么沒有成功彈出呢?
我們按F12,看一下報錯內容:

由此可以看出 test_var3 在函數執行后是沒有被定義的。說明在函數體內用 var 關鍵字聲明的變量 test_var3 是局部變量;
在函數體外使用 var 關鍵字定義的變量test_var1 和在函數體內未用任何關鍵字定義的變量 test_var2 是全局變量。
得出結論:
在函數體外使用var關鍵字定義的變量和在函數體內未用任何關鍵字聲明的變量是全局變量,在函數體內使用var關鍵字聲明的變量是局部變量。
var聲明的全局變量和局部變量同名
我們建立一個文件test2.html,從中輸入以下代碼:
<script type="text/javascript">
//在函數外使用var關鍵字聲明變量test_var
var test_var = "函數體外的變量";
//定義函數testFun
function testFun(){
//函數內使用var關鍵字聲明變量test_var
var test_var = "函數體內的變量";
//彈窗彈出test_var
alert(test_var);
}
//函數執行
testFun();
alert(test_var);
</script>
打開該文件,會彈出兩次彈窗,分別是:

點擊確定后還會彈窗一次:

在函數體外定義的全局變量test_var,但是在函數體內又定義了局部變量test_var ,在函數中彈出的test_var是函數體內的局部變量覆蓋函數體外的全局變量的結果,當離開函數后,局部變量失效,將會看到全局變量。
JavaScript中的變量有塊范圍嗎?
在Java、C、C++等語言中,在 if塊 ,循環塊中定義的變量,出了該塊之后將,不能繼續訪問。那JavaScript中是否也如此呢?
我們建立一個文件test3.html,從中輸入以下代碼:
<script type="text/javascript">
//定義函數testFun
function testFun(){
//函數內使用var關鍵字聲明變量test_var
var test_var1 = "1";
//if代碼塊
if(test_var1 == "1"){
//定義變量test_var2
var test_var2 = 10;
//for代碼塊
for(var i = 0; i < 5; i++){
//打印輸出i
document.write(i);
}
}
//在if塊外訪問test_var2
alert(test_var2);
//在循環體外訪問i
alert(i);
}
//函數執行
testFun();
</script>
我們可以看到兩個彈窗:


並且能看到頁面上的輸出

由此我們可以知道:
在函數體內中的 if 塊和循環體內定義的變量,在函數內都是可以訪問的。
變量提升
前面介紹中已經知道:局部變量和全局變量同名時,局部變量會覆蓋全局變量。
我們定義test4.html,輸入以下代碼:
<script type="text/javascript">
//在函數外使用var關鍵字聲明變量test_var
var test_var = "函數外的test_var";
//定義函數testFun
function testFun(){
//打印輸出test_var
document.writeln(test_var + "<br>");
//函數內使用var關鍵字定義的test_var
var test_var = "函數內的test_var";
//再次打印輸出test_var
document.writeln(test_var + "<br>");
}
//函數執行
testFun();
</script>
輸出如下:

在輸出全局變量時,居然輸出的是underfined,這是什么情況呢?
這便是JavaScript的變量提升機制起了”作用“。下面介紹一下變量提升:
在函數體內變量聲明總會被解釋器”提升“到函數體的頂部,
那么上面的代碼,會變成如下情況:
<script type="text/javascript">
//在函數外使用var關鍵字聲明變量test_var
var test_var = "函數外的test_var";
//定義函數testFun
function testFun(){
//聲明被提升到頂部,但是未被賦值
var test_var;
//打印輸出test_var
document.writeln(test_var + "<br>");
//給test_var賦值
test_var = "函數內的test_var";
//再次打印輸出test_var
document.writeln(test_var + "<br>");
}
//函數執行
testFun();
</script>
由此可見,變量提升只提升聲明部分,不提示賦值部分。
我們定義test5.html,輸入以下代碼:
<script type="text/javascript">
//在函數外使用var關鍵字聲明變量test_var1
var test_var1 = "函數外的test_var1";
//在函數外使用var關鍵字聲明變量test_var2
var test_var2 = "函數外的test_var2";
//定義函數testFun
function testFun(){
//打印輸出test_var1
document.writeln(test_var1 + "<br>");
//打印輸出test_var2
document.writeln(test_var2 + "<br>");
//for循環的條件為假不會被執行
for(;-1>5;){
//在函數內使用var關鍵字聲明變量test_var1
var test_var1 = "函數內的test_var1";
}
return;
//return后面的語句不會被執行
//在函數內使用var關鍵字聲明變量test_var2
var test_var2 = "函數內的test_var2";
}
//函數執行
testFun();
</script>
輸出如下:

在函數內的 test_var1 和 test_var2 的變量定義根本不會被執行,為何還是輸出undefined呢?
這也是變量提升起的”作用“。
let關鍵字定義變量
從前面我們可以看到,var定義的變量沒有塊作用域,還有變量提升機制,為了克服這些問題,便引入了let關鍵字。
我們定義test6.html,輸入以下代碼:
<script type="text/javascript">
//循環體
for(let v = 0;v < 5;v++){
//在循環體內輸出v
console.log(v);
}
//在循環體外輸出v
console.log(v);
</script>
按F12,打開console,看到輸出如下:

可以看到在循環體外不能訪問循環體內定義的變量。
我們定義test7.html,輸入以下代碼:
<script type="text/javascript">
//在函數外使用let關鍵字聲明變量test_var
let test_var = "函數外的test_var";
//定義函數testFun
function testFun(){
//打印輸出test_var
console.log(test_var);
//在函數內使用let關鍵字聲明變量test_var
let test_var = "函數內的test_var"
//打印輸出test_var
console.log(test_var);
}
//函數執行
testFun();
</script>
按F12,打開console,看到輸出如下:

這是因為函數內有和全局變量同名的局部變量,會覆蓋掉全局變量,但是let關鍵字聲明的變量並沒有提升機制,所以會報錯。
小結
本文介紹了JavaScript中的局部變量和全局變量的知識和var,let聲明變量的區別。給我們的啟示是如果瀏覽器支持let關鍵字,那么就盡量用let來避免變量提升機制等情況。
歡迎關注
掃下方二維碼即可關注,微信公眾號:code隨筆
