以前無論聲明變量還是常量,總是使用var一勺端,知道接觸了es6之后,發現原來變量、常量的聲明其實是很講究的。
這里簡單來談談var、const與let。
1、var。var聲明的變量沒有塊級作用域,而且存在變量名提升的情況。這里舉例說明。
<script>
var num = 123;
function foo(){
console.log(num); // undefined
var num = 46;
console.log(num) // 46
}
foo()
</script>
為什么第一個輸出值會是undefined,而不是123呢?因為這里存在着變量名的提升,其實上述語句相當於:
<script>
var num = 123;
function foo(){
var num;
console.log(num); // undefined
num = 46;
console.log(num) // 46
}
foo()
</script>
上面主要體現了var存在着變量名的提升,那么它沒有塊級作用域又是怎么體現的呢?最常見的是在條件語句里面,如if語句、for語句。這里以if語句為例。
<script>
var num = 123;
if(true){
console.log(num) // 123
var num = 456;
console.log(num) // 456
}
console.log(num) // 456
</script>
這里為什么第一個輸出值不是undefined,第三個輸出值不是123呢?原因是這樣的,因為var不存在塊級作用域,且變量名會提升,所以上述代碼其實相當於:
<script>
var num;
num = 123
if(true){
console.log(num) // 123
num = 456;
console.log(num) // 456
}
console.log(num) // 456
</script>
所以在我看來,var其實是有利有弊的,利就是不用去管什么常量與變量的,直接使用var就行,弊就是不存在塊級作用域且變量名會提升,這會在無形之中給我們帶來許多意想不到的問題
2、const(es6中用來定義常量的一個關鍵字(當然了,其他語言里也存在着const,這里僅指在js中)。常用來聲明常量,且常量不可修改,必須初始化,存在着塊級作用域。
(1)、不存在名稱提升問題。以代碼說事兒。
<script>
function foo(){
console.log(num);
const num = 456;
console.log(num)
}
foo()
</script>
運行上述代碼會發現會報錯 Uncaught ReferenceError: num is not defined 。這里說明,使用const來定義的常量名並沒有提升。
(2)、聲明時必須初始化。假如用const聲明的常量並沒有初始化呢?會有問題嗎?直接上代碼
<script>
const num;
console.log(num)
</script>
這里運行后發現會報錯。 Uncaught SyntaxError: Missing initializer in const declaration 意思是:語法錯誤,在const聲明中沒有初始化。
同樣的代碼,只是const聲明初始化,結果會不會有變化呢?答案是不言而喻的了。
(3)、存在着塊級作用域。什么叫塊級作用域呢?上代碼:
<script> const num = 456 if(true){ const num = 789; console.log(num); // 789 } console.log(num) // 456 </script>
可見在if語句內聲明的常量在if語句外並不能訪問到,這里與var不同。這里是以if語句為例的,當然在for語句亦或是函數內都是這樣的,存在着塊級作用域
3、let(es6中用來定義變量的一個關鍵字)。let定義的變量存在着塊級作用域,在函數內定義的變量,對函數外部無影響。
(1)、在函數內部定義的變量,對函數外部無影響,即存在着塊級作用域。
<script> let num = 789; function foo(){ let num = 46; console.log(num) // 46 } foo() console.log(num) // 789 </script>
(2)、不存在着變量名的提升。
<script>
function foo(){
console.log(num); // Uncaught ReferenceError: num is not defined
let num = 46;
console.log(num)
}
foo()
</script>
運行后發現會報錯,可見使用let聲明的變量,並不像var那樣存在着變量名的提升問題。
