塊級作用域
ES5 只有全局作用域和函數作用域, 沒有塊級作用域
ES6 新增塊級作用域概念 一對花括號 {} 即爲一個塊級作用域 if 語句和 for 語句裏面的 {} 也屬於塊作用域
- 沒有塊級作用域,將帶來很多不合理的場景
內層變量可能會覆蓋外層變量
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'helloworld';
}
}
f(); // undefined ---由於變量提升 導致內層的tmp覆蓋了外層的tmp
循環變量泄露爲全局變量
for (var i = 0; i < 3; i++) {
console.log(i);
}
console.log(i); // 3
- 塊級作用域的優勢
立即執行函數
(function(){ })();
//現在一個 {} 就可以代替
{}
外層代碼塊不受內層代碼塊的影響
{
let a = 1;
{
let a = 2;
}
console.log(a); //1
}
外層作用域無法讀取內層作用域的變量
{
{
let a = 2;
}
console.log(a); // ReferenceError: a is not defined
}
let 和 const 特點
- let 和 const 只在塊級作用域中有效
{
let a = 1;
var b = 2;
}
a // ReferenceError: a is not defined
b // 2
ES6 中 {} 即爲一個塊級作用域 所以在 {} 外面就無法訪問 let 聲明的變量
在 for 循環中使用 let
for(var i = 0; i<3;i++){
setTimeout(function(){
console.log(i); // 出3個3
}, 1000)
}
// var 聲明的變量 i 泄露爲全局變量 當執行 console.log(i) 時 循環已經走完了, i 最終爲 3
for(let j = 0; j<3;j++){
setTimeout(function(){
console.log(j); // 依次輸出 0 1 2
}, 1000)
}
// let 聲明的變量只在本輪循環有效 每次循環都是一個塊級作用域, j 也是一個新的變量
- let 和 const 不存在變量提升
console.log(a); // undefined
console.log(b); // ReferenceError: b is not defined
var a = 1;
let b = 2;
let 聲明的變量 b 不存在變量提升 所以在聲明之前使用 b 就會報錯
只要塊級作用域內存在let命令,它所聲明的變量就"綁定"這個區域,不再受外部的影響 在語法上稱爲"暫時性死區"(temporal dead zone,簡稱TDZ)
{
// TDZ開始
tmp = 'abc'; // ReferenceError: tmp is not defined
console.log(tmp); // ReferenceError: tmp is not defined
typeof tmp; // ReferenceError: tmp is not defined
let tmp; // TDZ結束
}
- let 和 const 不允許重複聲明
{
let a = 1;
var a = 2; // SyntaxError: Identifier 'a' has already been declared
}
// 下面例子是不會報錯的,下面有兩個代碼塊, 外層代碼塊不受內層代碼塊的影響
{
let a = 1;
{
let a = 2;
}
console.log(a) // 1
}
- 使用let 和 const聲明的變量不會綁在window對象上
var a = 1;
console.log(window.a); // 1
let b = 1;
console.log(window.b); // undefined
const
- const 聲明的變量表示只讀的常量 聲明的時候必須賦值
const a; // SyntaxError: Missing initializer in const declaration
const a = 1;
a = 2; // TypeError: Assignment to constant variable.
- const 只是保證變量名指向的地址不變,並不保證該地址的數據不變
const foo = {};
foo.prop = 123;
foo.prop // 123
foo = {}; // TypeError: Assignment to constant variable.
const a = [];
a.push('Hello'); // 可執行
a.length = 0; // 可執行
a = ['Dave']; // 報錯
//如果真的想將對象凍結,應該使用Object.freeze方法
const foo = Object.freeze({});
foo.prop = 123;
foo.prop // undefined