前言:隨着2015年6月 ECMAScript 6.0 發佈以來,有幾個新的變量聲明方式進入前端開發者的視線,即 let、const、import 和 class 命令,而這些新的聲明方式之中有兩個容易和 var 混淆,那就是 let 和 const。那這兩個新的聲明方式和咱們以前使用的 var 聲明方式有什麼不一樣呢,那麼是什麼緣由致使 ES6 推崇新的聲明方式摒棄傳統的聲明方式呢,讓咱們經過這篇文章一探究竟。javascript
let
的用法相似於 var
,可是 let
只在所在的代碼塊內有效,因此咱們通常使用 let
替代 var
。而 const
用來聲明常量。前端
讓咱們先看一看這張表:java
聲明方式 | 變量提高 | 暫時性死區 | 重複聲明 | 初始值 | 做用域 |
---|---|---|---|---|---|
var | 容許 | 不存在 | 容許 | 不須要 | 除塊級 |
let | 不容許 | 存在 | 不容許 | 不須要 | 塊級 |
const | 不容許 | 存在 | 不容許 | 須要 | 塊級 |
接下來咱們根據這幾個方面來介紹 var、let和const的區別:變量提高、暫時性死區、重複聲明、初始值和做用域。es6
概述:變量可在聲明以前使用。bash
首先看這三段代碼:函數
console.log(a);//正常運行,控制檯輸出 undefined
var a = 1;
複製代碼
console.log(b);//報錯,Uncaught ReferenceError: b is not defined
let b = 1;
複製代碼
console.log(c);//報錯,Uncaught ReferenceError: c is not defined
const c = 1;
複製代碼
var
命令常常會發生變量提高現象,按照通常邏輯,變量應該在聲明以後使用纔對。爲了糾正這個現象,ES6 規定 let
和 const
命令不發生變量提高,使用 let
和 const
命令聲明變量以前,該變量是不可用的。主要是爲了減小運行時錯誤,防止變量聲明前就使用這個變量,從而致使意料以外的行爲。學習
概述:若是在代碼塊中存在 let
或 const
命令,這個區塊對這些命令聲明的變量,從一開始就造成了封閉做用域。凡是在聲明以前就使用這些變量,就會報錯。ui
var tmp = 123;
if (true) {
tmp = 'abc';//報錯,Uncaught ReferenceError: tmp is not defined
let tmp;
}
複製代碼
這段代碼的原意是在 if 內定義外部的 tmp
爲 'abc'。spa
但現實是,存在全局變量 tmp
,可是塊級做用域內 let
又聲明瞭一個 tmp
變量,致使後者被綁定在這個塊級做用域中,因此在 let
聲明變量前,對 tmp
賦值就報錯了。code
概述:指在相同做用域內,重複聲明同一個變量。
let
和 const
命令聲明的變量不容許重複聲明:
function func(){
let a = 10;
const PI = 3.1415;
var a = 1;// 報錯,Uncaught SyntaxError: Identifier 'a' has already been declared
var PI = 3;// 報錯,Uncaught SyntaxError: Identifier 'PI' has already been declared
}
// 當調用func()時報錯,Uncaught SyntaxError: Identifier 'a' has already been declared
function func(){
let a = 10;
const PI = 3.1415;
let a = 1;// 報錯,Uncaught SyntaxError: Identifier 'a' has already been declared
const PI = 3;// 報錯,Uncaught SyntaxError: Identifier 'PI' has already been declared
}
複製代碼
var
是容許重複定義的,而這又會給咱們帶來什麼麻煩呢?
var i = 10;
for(var i = 0;i < 5;i++){
console.log(i);
}
console.log(i);// 輸出 5
複製代碼
對於學習過靜態(類型)語言的人知道,這段代碼要是替換成 c 語言或其餘靜態語言,輸出的結果應該是 10。然而對於 javascript 來講,這段代碼的輸出結果是 5。由於 var
命令沒有塊級做用域,因此 for 循環括號內的變量 i
會覆蓋外層 i
,並且 var
容許重複聲明,因此這段代碼中 i
被聲明瞭兩次,i
的最終結果就被 for 循環的 i 給覆蓋了。
因爲 const
聲明的是隻讀的常量,一旦聲明,就必須當即初始化,聲明以後值不能改變。
const PI = 3.1415;
PI = 3;// 報錯,Uncaught TypeError: Assignment to constant variable.
複製代碼
在 ES5 中只有全局做用域和函數做用域,沒有塊級做用域,這帶來不少不合理的場景。
第一種場景,內層變量可能會覆蓋外層變量。
var tmp = new Date();//處於全局做用域
function f() {
console.log(tmp);//處於函數做用域
if (false) {
var tmp = 'hello world';
}
}
f(); // undefined
複製代碼
上面代碼的原意是,if
代碼塊的外部使用外層的tmp
變量,內部使用內層的tmp
變量。
然而現實是在這段代碼中,function 內部的2個 tmp
變量處在同一函數做用域,因爲變量提高,致使函數做用域中的 tmp
覆蓋全局做用域中的 tmp
,因此,f()輸出結果爲undefined。
第二種場景,用來計數的循環變量泄露爲全局變量(前面在重複聲明中提到的):
var i = 10;
for(var i = 0;i < 5;i++){
console.log(i);
}
console.log(i);// 輸出 5
複製代碼
上面代碼中,變量i
只用來控制循環,可是循環結束後,它並無消失,泄露成了全局變量。
本文內容以阮一峯的《ECMAScript 6 入門》爲基礎進行總結,歡迎各位提出文章內容中有錯誤和疑惑的地方~