1. ECMAScript 6 簡介
ECMAScript 6.0(以下簡稱 ES6)是 JavaScript 語言的下一代標(biāo)準(zhǔn),已經(jīng)在 2015 年 6 月正式發(fā)布了也拜。它的目標(biāo)衡招,是使得 JavaScript 語言可以用來編寫復(fù)雜的大型應(yīng)用程序力试,成為企業(yè)級開發(fā)語言肪虎。
(1) ECMAScript 和 JavaScript 的關(guān)系
ECMAScript 和 JavaScript 的關(guān)系是豌研,前者是后者的規(guī)格糯笙,后者是前者的一種實現(xiàn)(另外的 ECMAScript 方言還有 Jscript 和 ActionScript)贬丛。日常場合,這兩個詞是可以互換的给涕。
(2) ES6 與 ECMAScript 2015 的關(guān)系
ES6 既是一個歷史名詞豺憔,也是一個泛指,含義是 5.1 版以后的 JavaScript 的下一代標(biāo)準(zhǔn)够庙,涵蓋了 ES2015恭应、ES2016、ES2017 等等耘眨,而 ES2015 則是正式名稱昼榛,特指該年發(fā)布的正式版本的語言標(biāo)準(zhǔn)。
2. let 和 const 命令
(1) let 命令
- ES6 新增了let命令剔难,用來聲明變量胆屿。它的用法類似于var,但是所聲明的變量偶宫,
只在let命令所在的代碼塊內(nèi)有效非迹。
for循環(huán)還有一個特別之處,就是設(shè)置循環(huán)變量的那部分是一個父作用域读宙,而循環(huán)體內(nèi)部是一個單獨的子作用域彻秆。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
不存在變量提升
let命令改變了語法行為楔绞,它所聲明的變量一定要在聲明后使用结闸,否則報錯。
3.
暫時性死區(qū)
- 在代碼塊內(nèi)酒朵,使用let命令聲明變量之前桦锄,該變量都是不可用的。這在語法上蔫耽,稱為“暫時性死區(qū)”(temporal dead zone结耀,簡稱 TDZ)留夜。
- 只要塊級作用域內(nèi)存在let命令,它所聲明的變量就“綁定”(binding)這個區(qū)域图甜,不再受外部的影響碍粥。
- 暫時性死區(qū)的本質(zhì)就是,只要一進入當(dāng)前作用域黑毅,所要使用的變量就已經(jīng)存在了嚼摩,但是不可獲取,只有等到聲明變量的那一行代碼出現(xiàn)矿瘦,才可以獲取和使用該變量枕面。
不允許重復(fù)聲明
let不允許在相同作用域內(nèi),重復(fù)聲明同一個變量缚去。
(2) 塊級作用域
為什么需要塊級作用域潮秘?
- 第一種場景,內(nèi)層變量可能會覆蓋外層變量易结。(變量提升)
- 第二種場景枕荞,用來計數(shù)的循環(huán)變量泄露為全局變量。
ES6 的塊級作用域
let實際上為 JavaScript 新增了塊級作用域搞动。
- ES6 允許塊級作用域的任意嵌套买猖。
- 外層作用域無法讀取內(nèi)層作用域的變量。
- 內(nèi)層作用域可以定義外層作用域的同名變量滋尉。
塊級作用域與函數(shù)聲明
ES5 規(guī)定玉控,函數(shù)只能在頂層作用域和函數(shù)作用域之中聲明,不能在塊級作用域聲明狮惜。
ES6 引入了塊級作用域高诺,明確允許在塊級作用域之中聲明函數(shù)。ES6 規(guī)定碾篡,塊級作用域之中虱而,函數(shù)聲明語句的行為類似于let,在塊級作用域之外不可引用开泽。
function f() { console.log('I am outside!'); }
(function () {
if (false) {
// 重復(fù)聲明一次函數(shù)f
function f() { console.log('I am inside!'); }
}
f();
}());
上面代碼在 ES5 中運行牡拇,會得到“I am inside!”,因為在if內(nèi)聲明的函數(shù)f會被提升到函數(shù)頭部穆律,實際運行的代碼如下惠呼。
// ES5 環(huán)境
function f() { console.log('I am outside!'); }
(function () {
function f() { console.log('I am inside!'); }
if (false) {
}
f();
}());
ES6 瀏覽器的實現(xiàn)可以不遵守上面的規(guī)定,有自己的行為方式
- 允許在塊級作用域內(nèi)聲明函數(shù)峦耘。
- 函數(shù)聲明類似于var剔蹋,即會提升到全局作用域或函數(shù)作用域的頭部。
- 同時辅髓,函數(shù)聲明還會提升到所在的塊級作用域的頭部泣崩。
根據(jù)這三條規(guī)則少梁,在瀏覽器的 ES6 環(huán)境中,塊級作用域內(nèi)聲明的函數(shù)矫付,行為類似于var聲明的變量凯沪。
// 瀏覽器的 ES6 環(huán)境
function f() { console.log('I am outside!'); }
(function () {
if (false) {
// 重復(fù)聲明一次函數(shù)f
function f() { console.log('I am inside!'); }
}
f();
}());
// Uncaught TypeError: f is not a function
上面的代碼在符合 ES6 的瀏覽器中,都會報錯买优,因為實際運行的是下面的代碼著洼。
// 瀏覽器的 ES6 環(huán)境
function f() { console.log('I am outside!'); }
(function () {
var f = undefined;
if (false) {
function f() { console.log('I am inside!'); }
}
f();
}());
// Uncaught TypeError: f is not a function
考慮到環(huán)境導(dǎo)致的行為差異太大,應(yīng)該避免在塊級作用域內(nèi)聲明函數(shù)而叼。如果確實需要身笤,也應(yīng)該寫成
函數(shù)表達式
,而不是函數(shù)聲明語句葵陵。
// 函數(shù)聲明語句
{
let a = 'secret';
function f() {
return a;
}
}
// 函數(shù)表達式
{
let a = 'secret';
let f = function () {
return a;
(3) const 命令
const聲明一個只讀的常量液荸。一旦聲明,常量的值就不能改變脱篙。
- const聲明的變量不得改變值娇钱,這意味著,
const一旦聲明變量绊困,就必須立即初始化
文搂,不能留到以后賦值。- const的作用域與let命令相同:
只在聲明所在的塊級作用域內(nèi)有效秤朗。
- const命令聲明的
常量也是不提升
煤蹭,同樣存在暫時性死區(qū)
,只能在聲明的位置后面使用取视。- const聲明的常量硝皂,也與let一樣
不可重復(fù)聲明
。
本質(zhì)
:
const實際上保證的作谭,并不是變量的值不得改動稽物,而是變量指向的那個內(nèi)存地址所保存的數(shù)據(jù)不得改動。對于簡單類型的數(shù)據(jù)(數(shù)值折欠、字符串贝或、布爾值),值就保存在變量指向的那個內(nèi)存地址锐秦,因此等同于常量咪奖。但對于復(fù)合類型的數(shù)據(jù)(主要是對象和數(shù)組),變量指向的內(nèi)存地址农猬,保存的只是一個指向?qū)嶋H數(shù)據(jù)的指針赡艰,const只能保證這個指針是固定的(即總是指向另一個固定的地址),至于它指向的數(shù)據(jù)結(jié)構(gòu)是不是可變的斤葱,就完全不能控制了慷垮。
(4) 頂層對象的屬性
- 頂層對象,在瀏覽器環(huán)境指的是window對象揍堕,在 Node 指的是global對象料身。ES5 之中,頂層對象的屬性與全局變量是等價的衩茸。
- ES6 為了改變這一點芹血,一方面規(guī)定,為了保持兼容性楞慈,var命令和function命令聲明的全局變量幔烛,依舊是頂層對象的屬性;另一方面規(guī)定囊蓝,let命令饿悬、const命令、class命令聲明的全局變量聚霜,不屬于頂層對象的屬性狡恬。