var
語法babel
var varname1 [= value1 [, varname2 [, varname3 ... [, varnameN]]]];
使用閉包
var a, b=2 // 聲明多個變量,能夠賦值,也能夠不賦值 a=1 // 先聲明,再賦值
var
變量提高
使用var
聲明的變量將會被提高到函數的頂部app
console.log(a) // undefined var a =2 console.log(a) // 2 console.log(b) //Uncaught ReferenceError: b is not defined...
以上代碼至關於函數
var a console.log(a) // undefined a=2 console.log(a) // 2 console.log(b) //Uncaught ReferenceError: b is not defined...
let
語法翻譯
let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]];
使用code
let a, b = 2 // 聲明多個變量,賦值不賦值無所謂 a = 2 // 聲明以後再賦值
再也不提高事件
console.log(a) // Uncaught ReferenceError: a is not defined... let a=1
注意:猜想, 使用babel
翻譯一下代碼發現,只是let
變成了var
,因此使用babel
轉義以後的代碼依舊會提高作用域
不能重複聲明get
let a=1 let a=2 // Uncaught SyntaxError: Identifier 'a' has already been declared
語言it
const name1 = value1 [, name2 = value2 [, ... [, nameN = valueN]]];
使用
const a=1, b=2 // 不能省略的值
不能省略的值
const c // Uncaught SyntaxError: Missing initializer in const declaration
不能重複賦值
const d=4 d=5 // Uncaught TypeError: Assignment to constant variable.
能夠修改的引用
const e=[] e[0]=0 console.log(e) //[0]
塊級做用域是隨着let
、const
而來最有用的特性了,在以前的js
中,js
的做用域是函數級的,由此帶來的幾個臭名昭著的問題:
意外被修改的值
function varTest() { var x = 1; if (true) { var x = 2; // 一樣的變量! console.log(x); // 2 } console.log(x); // 2 }
可使用let
避免了
function letTest() { let x = 1; if (true) { let x = 2; // 不一樣的變量 console.log(x); // 2 } console.log(x); // 1 }
萬惡的for
循環和點擊事件
var list = document.getElementById("list"); for (var i = 0; i < 5; i++) { var item = document.createElement("LI"); item.appendChild(document.createTextNode("Item " + i)); item.onclick = function (ev) { console.log("Item " +i + " is clicked."); }; list.appendChild(item); } console.log(i) // 5
若是點擊上面,無論點擊哪一個,顯示出來的都是Item 5 is clicked.
,雖然可使用閉包解決,可是如今有了更好的方案
let list = document.getElementById("list"); for (let i = 0; i < 5; i++) { let item = document.createElement("LI"); item.appendChild(document.createTextNode("Item " + i)); item.onclick = function (ev) { console.log("Item " +i + " is clicked."); }; list.appendChild(item); }
{}
塊內造成一個做用域,包括if
、else
、while
、class
、do...while
、{}
、function
{ const f=6 } console.log(f) // Uncaught ReferenceError: f is not defined
for
循環中用let
聲明一個初始因子,該因子在每一個循環內都是一個新的做用域
for (let i = 0; i < 10; i++) { console.log(i); } console.log(i) // Uncaught ReferenceError: i is not defined
switch
只有一個做用域
switch (x) { case 0: let foo; break; case 1: let foo; break; } // Uncaught SyntaxError: Identifier 'foo' has already been declared
Temporal Dead Zone
-TDZ
隨着let
和const
的引入,也引入了暫存死區的概念。使用var
的時候,做用域內(函數做用域),在還沒使用var
聲明一個變量的時候,訪問該變量,將會得到undefined
。可是若是使用let
,做用域(塊級做用域)內,在還沒使用let
聲明一個變量的時候,訪問該變量,將會得到ReferenceError
,從做用域開始到let
語句之間,就是暫存死區。
{ console.log(a) // Uncaught ReferenceError: a is not defined console.log(b) // Uncaught ReferenceError: b is not defined console.log(c) // undefined // 暫存死區 let a =1 const b=2 var c=3 }
注意:猜想, 使用babel
翻譯一下代碼發現,只是let
變成了var
,因此使用babel
轉義以後可能不存在暫存死區
儘可能使用let
和const
,若是但願改變該變量的值,則使用let
,若是但願再也不改變該變量的值或者引用,則使用const
,讓var
成爲歷史。