ES6系列之let和const與var的區別

ES6規範新增了let、const兩種變量聲明方式,項目中也常常要用到,今天藉着溫習ES6語法,來總結let 、const、var的區別。javascript

1、變量提高

來看下面三段代碼java

console.log(a); // undefined
var a = 2;
console.log(b); // Uncaught ReferenceError: b is not defined
let b = 2;
console.log(c); // Uncaught ReferenceError: c is not defined
const c = 2;

用var聲明的變量,會在其做用域中發生變量提高,js默認給變量一個undefined值。es6

可是,在ES6中使用let/const聲明的變量,不存在變量提高過程。也就是說,在使用let/const聲明的變量,聲明前訪問它,都會報錯。閉包

2、暫時性死區

代碼塊內,使用let命令聲明變量以前,該變量都是不可用的。這在語法上,稱爲「暫時性死區」(temporal dead zone,簡稱 TDZ)。
let a = 'global';
if (true) {
    a = 'block';    // Uncaught ReferenceError: a is not defined
    let a;
}

上述代碼中,if代碼塊裏,在let聲明變量a以前,都是a的"暫時性死區",在該範圍內訪問a都會報錯。
因而可知,塊級做用域內存在let聲明的話,它所聲明的變量就綁定在這個塊級做用域,再也不受外部影響。函數

3、重複聲明

let 和 const 命令聲明的變量不容許重複聲明;而使用var聲明變量,能夠屢次重複聲明一個同名變量,但最終變量的值爲最後一次聲明賦值的結果。指針

var a = 10;
var a = 'abc';
var a = 'last value';
console.log(a);  // last value

let與const在相同做用域聲明重複的變量會報錯code

let a = 10;
let a = 20; // Uncaught SyntaxError: Identifier 'a' has already been declared

var和let同時聲明同一個變量,也是報一樣的錯誤對象

let b = 10;
var b = 20; // Uncaught SyntaxError: Identifier 'b' has already been declared

或先var,再letip

var c = 10;
let c = 20; // Uncaught SyntaxError: Identifier 'c' has already been declared

4、做用域

這裏就涉及到一個最經典的問題:內存

for (var i = 0; i < 5; i++) { 
    setTimeout(function() { 
        console.log(i); // 5 5 5 5 5 
    });
}

這個問題的解決可使用閉包等,ES6的let爲這個問題提供了新的解決方法:

for (let i = 0; i < 5; i++) { 
    setTimeout(function() { 
        console.log(i); // 0 1 2 3 4
    });
}

使用let聲明的變量僅在塊級做用域內有效。 i在循環體內的局部做用域,不受外界影響。

在ES6以前,都是用var來聲明變量,並且JS只有函數做用域和全局做用域,沒有塊級做用域,因此花括號{}限定不了var聲明變量的訪問範圍。

{ 
  var a = 10;
} 
console.log(a);  // 10

{ 
  let b = 9;     // es6的let: b變量只在花括號內有效
} 
console.log(b);  // Uncaught ReferenceError: b is not defined

5、let、const聲明的全局變量不會做爲window對象的一個屬性

使用var聲明的全局變量,會被JS自動添加在全局對象window上,但let和const不會

let a = 10;
console.log(window.a); // undefined

var b = 20;
console.log(window.b); // 20

const c = 30;
console.log(window.c); // undefined

6、const聲明常量

因爲const用來聲明常量,一旦聲明,就必須當即初始化,並且聲明以後值不能改變。

const a = 10;
a = 20; // Uncaught TypeError: Assignment to constant variable.

常量的值不變,其實是指常量指向的那個內存地址中所保存的數據不可更改。

對於基本數據類型(數值,字符串、布爾值),他們自己具體的值就保存在常量所指向對應的棧內存地址中,因此修改值就等於修改棧內存地址,這顯然不容許會報錯。

可是,若是一個常量的值是一個引用類型值,那麼常量所指向的內存地址(堆內存)中實際保存的是指向該引用類型值的一個指針(也就是引用類型值在內存中的地址)。因此const只能保證該引用類型地址不變,但該地址中的具體數據是能夠變化的。

以下代碼:

const obj = {};
obj.a = 3;
console.log(obj); // {a: 3}

// 當obj指向了另外一個對象,即obj中保存的地址發生了變化,即會報錯
obj = {};  // Uncaught TypeError: Assignment to constant variable.

如何正確使用

在開發的時候,聲明變量咱們應該少使用var,避免產生沒必要要的全局變量。當須要改變變量的值時聲明用let,對於須要寫保護的變量或定義常量使用const。

相關文章
相關標籤/搜索