1、let 命令
ES6新增了let,用來聲明變量,它的用法類似於 var
,但是所聲明的變量,只在let
命令所在的代碼塊內有效。
{
let a = 1
var b = 2
}
console.log(a) // ReferenceError: a is not defined.
console.log(b) // 2
下面講述下 let 相對於 var 的特性
變量提升和暫時性死區
先來看一個例子
// var 的情況
console.log(a); // 輸出undefined
var a = 2;
// let 的情況
{
console.log(b); // 報錯ReferenceError
let b = 2;
}
上面的代碼中 var 聲明的變量發生了變量提升,即腳本開始運行時,變量a已經存在了,但是沒有值,所以會輸出undefined。注意一個細節,變量聲明分爲兩部分,創建和初始化
var 聲明的時候,創建跟初始化過程都提升了,但是let 只有創建的時候發生了提升,初始化並沒有提升,下面看下過程.
var 的情況
- 找到所有用 var 聲明的變量,在環境中「創建」這些變量
- 將這些變量「初始化」爲 undefined。
- 開始執行代碼
- a = 2 將 a 變量「賦值」爲 1
也就是說 var 聲明會在代碼執行之前就將「創建變量,並將其初始化爲 undefined」。
這就解釋了爲什麼在 var a = 2 之前 console.log(a) 會得到 undefined。
let 的情況
- 找到所有用 let 聲明的變量,在環境中「創建」這些變量
- 開始執行代碼(注意現在還沒有初始化)
- 執行 b = 2,將b 「初始化」爲 2(這並不是一次賦值,如果代碼是 let b,就將 b 初始化爲 undefined)
發現什麼區別沒有,let在執行代碼之前並沒有對變量進行初始化。也就是說let聲明變量,只有創建過程發生了提升。
ES6 明確規定,如果區塊中存在let
和const
命令,這個區塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報錯。
所謂暫時死區,就是不能在初始化之前,使用變量。
塊級作用域
ES5 只有全局作用域和函數作用域,沒有塊級作用域,這帶來很多不合理的場景。例如:
// 第一種
var str = 'outside'
function f() {
console.log(tmp);
if (true) {
var str = 'indside';
}
}
f(); // undefined
// 第二種
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]);
}
console.log(i); // 5
上面代碼,函數f
執行後,輸出結果爲undefined
,原因在於變量提升,導致內層的 str 變量覆蓋了外層的tmp
變量。第二種for循環,用來計數的循環變量泄露爲全局變量。如果用let來寫循環,例如:
for (let i = 0; i < 5; i++) {
let i = 'Tom'
console.log(i) // 輸出Tom 5 次
}
console.log(i) // i is not defined
上面的循環就充分的體現了let 的塊級作用域特性,for循環的條件判斷是一個隱藏的塊級,循環主題是另外一個塊級,所以可以有兩個變量i,互不干擾,同時循環變量在循環結束後就被回收了。
不允許重複聲明
let
不允許在相同作用域內,重複聲明同一個變量。
function aa () {
var a = 11
var a = 22
}
aa() // 不報錯
function bb () {
var a = 11
let a = 22
}
bb() // 報錯
function cc () {
let a = 11
let a = 22
}
cc() // 報錯
function dd () {
let a = 11
{
let a = 22
}
}
dd() // 不報錯
2、const命令
const
用來聲明一個只讀的常量,一旦聲明,常量的值就不能改變。
const PI = 3.1415;
console.log(PI) // 3.1415
PI = 3 // TypeError
const
一旦聲明變量,就必須立即初始化,不能留到以後賦值。
const a;
// SyntaxError: Missing initializer in const declaration
const
實際上保證的,並不是變量的值不得改動,而是變量指向的那個內存地址所保存的數據不得改動。如果聲明的數據類型是引用型,是可以改變的
const arr = []
arr.push('a') // 可以執行
arr = 2 // 報錯
const
命令聲明的常量也是不提升,同樣存在暫時性死區,只能在聲明的位置後面使用。
{
console.log(A) // ReferenceError
const A = 5
}
到這裏差不多講的都差不多了,let 跟 const 是 es6 新增的兩種聲明變量的命令,還有其他幾種聲明命令分別是 var ,function ,import ,class 。有興趣的小夥伴可以去了解下~