系列文章 -- ES6筆記系列html
咱們都知道,在ES6之前,JS只有函數級做用域,沒有塊級做用域這個概念閉包
沒有塊級做用域,有利有弊,利於方便自由,弊於做用域內的變量容易被共享,例如這個例子函數
var a = []; for (var i = 1; i <= 10; ++i) { a[i] = function() { return i; }; } a[3]() // 11
循環中變量i是處於全局做用域下的,其實這裏是個閉包,函數內部的i與函數外的i造成了引用的關係,致使函數退出以後i未被銷燬,引用的依然是全局的ispa
循環完成,此時i已是11,調用之,則值皆爲11code
這是沒有塊級做用域支持的經典例子,ES6則引入了這個特性,經過let關鍵字,造成「塊級的做用域」htm
let和var相似,用來聲明變量,那麼,把上方中的var換成let對象
var a = []; for (let i = 1; i <= 10; ++i) { a[i] = function() { return i; }; } a[3]() // 3
這是正確的結果,由於let使for循環變成了一個「塊級做用域」,相似的還有if、while的「塊級做用域」blog
if (1) { let a = 10; var b = 11; } console.log(a); // undefined console.log(b); // 11
1)不能重複聲明,var重複聲明會被覆蓋,但let重複聲明會報錯內存
var aa = 1; var aa = 2; let bb = 1; let bb = 2; // Uncaught SyntaxError: Identifier 'bb' has already been declared
2)不存在變量提高,以下作法會報錯作用域
console.log(a2); // Uncaught ReferenceError: a2 is not defined console.log(b); // undefined let a2 = 10; var b = 11;
3) 存在暫時性死區(temporal dead zone),只要塊級做用域內存在let的聲明,它所聲明的變量就「綁定」(binding)這個區域,再也不受外部的影響
var a3 = 3; if (1) { a3 = 1; // Uncaught ReferenceError: a3 is not defined let a3; }
此外,不單是顯示的let才存在死區這種狀態,在函數的默認參數之中也會發生,以下的b未聲明則直接使用a = b會報錯
function bar(a = b, b = 2) { return [a, b]; } bar(); // Uncaught ReferenceError: b is not defined
4)let與window對象脫鉤
通常來講,全局var聲明的變量,會掛鉤在window對象上,但let卻不會這樣,如
var aa = 1; let bb = 1; console.log(window.aa); console.log(window.bb);
1)匿名函數
沒有塊級做用域以前,爲了整合代碼,更好的分塊不予外部代碼混淆,咱們經常使用匿名函數的自執行方式
(function() { console.log(1); // 1 })();
但或許如今再也不須要了,直接使用一對(或多對)大括號,就有了塊級的做用域
{ console.log(1); // 1 }
const聲明瞭一個只讀的常量,常量,即值不可更改。
const MAX = 10; MAX = 11; // Uncaught TypeError: Assignment to constant variable.
const除了擁有let上述的特色以外,還有一些要注意的點
1)const一旦聲明變量,就必須當即初始化,不然報錯
const MAX; // Uncaught SyntaxError: Missing initializer in const declaration
2) const聲明的引用類型
const聲明的引用類型,只是引用類型的地址不能更改,但其指向的值是能夠的,如
const obj = { a: 10 }; obj.a = 11; obj.a // 11