ES6研習:let和const指令
1. let
指令
let
基本用法 :
ES6 新增了
let
指令,用來聲明變量。
注意:所有生命的變量旨在
let
指令所在代碼塊中有效,也就是
{}
中
{
let a = 10;
var b = 1;
}
a // ReferenceError: a is not defined.
b // 1
1.1 不存在變量提升
變量提升 :
var
指令會發生“變量提升”現象,即變量可以在聲明之前使用,值為
undefined
。
這樣很容易出現各種問題,
let
聲明的變量不存在變量提升
// var 的情況
console.log(foo); // 輸出undefined
var foo = 2;
// let 的情況
console.log(bar); // 報錯ReferenceError
let bar = 2;
1.2暫時性死區
在代碼塊内,使用 let
指令聲明變量之前,該變量都是不可用的。這在文法上,稱為“暫時性死區”(temporal dead zone,簡稱 TDZ)。
if (true) {
// TDZ開始
tmp = 'abc'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp; // TDZ結束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
注意:沒有變量提升和有暫時性死區後,typeof關鍵字可能會報錯
因為之前使用
var
關鍵字,沒有聲明的變量值都為
undefined
typeof x; // ReferenceError
let x;
typeof undeclared_variable // "undefined"
還有一些情況會報錯:
function bar(x = y, y = 2) {
return [x, y];
}
bar(); // 報錯
function bar(x = 2, y = x) {
return [x, y];
}
bar(); // [2, 2]
// 不報錯
var x = x;
// 報錯
let x = x;
// ReferenceError: x is not defined
總結 : 在ES6中使用
let
關鍵字聲明變量都應該先聲明再使用,這樣也可以避免很多不必要的錯誤
1.3不允許重複聲明
let
不允許在相同作用域内,重複聲明同一個變量。
// 報錯
function func() {
let a = 10;
let a = 1;
}
function func(arg) {
let arg;
}
func() // 報錯
1.4塊級作用域
ES5中有全局作用域和函數作用域,ES6添加塊級作用域。
ES5中的 var
關鍵字在很多時候都是不合理的,不管是變量提升還是作用域
ES6新增的塊級作用域可以了解為 {}
塊級作用域的特點 :
- 外層作用域無法讀取内層作用域的變量
- 内層作用域可以定義外層作用域的同名變量。
- 有了塊級作用域後就可以不需要立即執行函數了,解決了循環中的很多問題,像定時器,閉包等
// IIFE 寫法
(function () {
var tmp = ...;
...
}());
// 塊級作用域寫法
{
let tmp = ...;
...
}
注意:不要忘記在循環語句的
()
裡面會形成一個單獨的作用域
2. const
指令
const
const
聲明一個隻讀的常量。一旦聲明,常量的值就不能改變。
2.1 基本用法
const PI = 3.1415;
PI // 3.1415
PI = 3;
// TypeError: Assignment to constant variable.
const特點 :
- 聲明常量,一旦聲明不能改變
- 一旦聲明,必須指派不可以留到以後指派
- 不存在變量提升,同樣存在暫時性死區,隻能聲明後使用
2.2 實質
-
不是保證值不變,而是保證變量指向的位址不變,對于基本資料類型變量是直接指向記憶體位址的,是以等同于常量const
- 但是對于對象而言,記憶體儲存的是一個指針,是以使用
聲明對象時不能重新指派其他對象但是可以為其添加屬性const
const foo = {};
// 為 foo 添加一個屬性,可以成功
foo.prop = 123;
foo.prop // 123
// 将 foo 指向另一個對象,就會報錯
foo = {}; // TypeError: "foo" is read-only
2.3當機對象
如果真的想将對象當機,應該使用 Object.freeze
方法。
const foo = Object.freeze({});
// 正常模式時,下面一行不起作用;
// 嚴格模式時,該行會報錯
foo.prop = 123;
除了将對象本身當機,對象的屬性也應該當機。下面是一個将對象徹底當機的函數。
var constantize = (obj) => {
Object.freeze(obj);
Object.keys(obj).forEach( (key, i) => {
if ( typeof obj[key] === 'object' ) {
constantize( obj[key] );
}
});
};
個人部落格:http://www.aeiherumuh10.com/zeno-blog/
參考文獻:https://es6.ruanyifeng.com/#docs/let