簡介
ECMAScript 和 JavaScript 的關(guān)系是,前者是后者的規(guī)格,后者是前者的一種實(shí)現(xiàn)。
現(xiàn)在通用的是ES5(ES3)。
ES6每年都有一次更新,所以具體版本如ES2015指的是ES6的2015年版本。
let和const
Let
let不同于var,let具有塊級(jí)作用域概念,let不會(huì)提升變量。
let存在暫時(shí)性死區(qū),在代碼塊內(nèi),使用let命令聲明變量之前,該變量都是不可用的。這在語法上,稱為“暫時(shí)性死區(qū)”(temporal dead zone,簡稱 TDZ),同樣的在死區(qū)使用typeof()也是輝報(bào)錯(cuò)的。
let不允許重復(fù)聲明。
let定義的變量不會(huì)存在于全局對(duì)象的屬性中。
const
const類似于let,const指向的內(nèi)存被鎖死,無法被改變。
變量的存儲(chǔ)分簡單和復(fù)雜,簡單類型存儲(chǔ)的是數(shù)據(jù),復(fù)雜類型存儲(chǔ)的是指針。
使用Object.freeze()對(duì)對(duì)象進(jìn)行凍結(jié)。
變量解構(gòu)
ES6允許按照一定模式,從數(shù)組和對(duì)象中提取值,對(duì)變量進(jìn)行賦值,稱為解析。
這種模式方便解析數(shù)組和對(duì)象。
這種寫法屬于 "模式匹配" ,只要兩邊模式相等,左邊的變量就會(huì)被賦予對(duì)應(yīng)的值。
數(shù)組解構(gòu)
數(shù)組解構(gòu)是按照排列順序的
下面的let中實(shí)際上是先定義了var1... ,
然后([var1, [var21, var23], var3] = [1, [2, 6], 3]);
let [var1, [var21, var23], var3] = [1, [2, 6], 3];
var1 : 1, var21 : 2, var23 : 6, var3 : 3
let[var1, ...var2] = [1, [2, 6], 3];
var1 : 1, var2 : [[2,6], 3]
不完全解構(gòu)
let [var1, [var21], var3] = [1, [2, 6], 3]
var1 :1,
var21 : 2,
var3 : 3
解構(gòu)賦值允許指定默認(rèn)值。默認(rèn)值生效的條件是,對(duì)象的屬性值嚴(yán)格等于undefined,使用函數(shù)賦值會(huì)是惰性求值。
let [var1, [var21, var22 , var23 = 8 ], var3] = [1, [2, 6], 3]
var1 : 1
var21 : 2
var22 : 6
var23 : 8
var3 : 3
對(duì)象解構(gòu)
對(duì)象解構(gòu)是依據(jù)對(duì)象屬性名進(jìn)行解析的
對(duì)象的解構(gòu)賦值可以取到繼承的屬性。
let {foo ,bar} = {foo : 'aaa', bar : 'ccc'};
//等于
let {foo : foo, bar : bar} = {foo : 'aaa', bar : 'ccc'}
foo : foo //前者是匹配模式,后者是賦予的變量
嵌套
let {info : {name : Name}, score : [score1, score2, score3]} =
{ info : {name : 'Name'}, score : [99 , 98 ,99]}
Name : 'Name'
score1 : 99
score2 : 98
score3 : 99
解構(gòu)賦值的規(guī)則 :?只要等號(hào)右邊的值不是對(duì)象或數(shù)組,就先將其轉(zhuǎn)為對(duì)象。由于undefined和null無法轉(zhuǎn)為對(duì)象,所以對(duì)它們進(jìn)行解構(gòu)賦值,都會(huì)報(bào)錯(cuò)。但是像字符串,數(shù)組,布爾都可以。
函數(shù)參數(shù)的解構(gòu)
函數(shù)的參數(shù)也可以使用解構(gòu)賦值。
function({x, y })
{
? ? //傳入的參數(shù)會(huì)被解構(gòu)
????//傳入?yún)?shù)也可以使用默認(rèn)值
? ? //也可以使用函數(shù)自帶默認(rèn)值
}
注意點(diǎn)
// 正確的寫法 let x;
({x} = {x: 1}); //必須加上括號(hào)‘
Module的語法
ES6有自帶的模塊加載方案,Node.js使用的是CommonJS的模塊加載方案。
CommonJS
CommonJS的模塊加載方案使用在服務(wù)器端。
CommonJS的關(guān)鍵詞 : require? ? Module.exports? ?export
let{stat,exists,readFile}=require('fs');
由于CommonJS輸出是值的拷貝
var counter = 3;
function incCounter() {
? counter++;
}
module.exports = {
? get counter() {
? ? return counter
? },
? incCounter: incCounter,
};
CommonJS特性
運(yùn)行時(shí)加載。
使用exports輸出的時(shí)值的拷貝,而非引用。
ES6模塊
ES6模塊加載方案可以在服務(wù)端和瀏覽器都運(yùn)行。
ES6的關(guān)鍵詞 : import export
export
這種方式輸出的接口名稱跟變量名一樣
//第一種
export var firstName = 'Hong';
export Class {};
export function FuncName() {};
//第二種
var firstName = 'Hong';
export {firstName};
指定輸出接口的名稱
var firstName = 'Hong';
export { firstName as fName};
默認(rèn)輸出
export default xxx;
import
JS 文件通過import命令加載模塊
輸出的接口只讀,無法修改
import {firstName} from ’./moduleName.js‘
輸出的變量重命名
import {firstName as fName} from 'xxx'
由于import是靜態(tài)執(zhí)行,所以不能使用表達(dá)式和變量,這些只有在運(yùn)行時(shí)才能得到結(jié)果的語法結(jié)構(gòu)。
import語句會(huì)執(zhí)行所加載的模塊,因此可以有下面的寫法。
import 'lodash';
模塊的整體加載
export? * as obj from 'xxxx'
模塊的默認(rèn)加載
export defaultName from 'xxxx'
//加載默認(rèn)輸出
Module的加載
瀏覽器加載
瀏覽器加載ES6模塊,也使用<script>標(biāo)簽,
要加上 type = "module"屬性。
瀏覽器對(duì)于帶有type="module"的<script>,都是異步加載,不會(huì)造成堵塞瀏覽器,即等到整個(gè)頁面渲染完,再執(zhí)行模塊腳本,等同于打開了<script>標(biāo)簽的defer屬性。
<script type="module" src="./foo.js"></script>
jquery就支持模塊加載。
引入的模塊特性
代碼是在模塊作用域之中運(yùn)行,而不是在全局作用域運(yùn)行。模塊內(nèi)部的頂層變量,外部不可見。
模塊腳本自動(dòng)采用嚴(yán)格模式,不管有沒有聲明use strict。
模塊之中,可以使用import命令加載其他模塊(.js后綴不可省略,需要提供絕對(duì) URL 或相對(duì) URL),也可以使用export命令輸出對(duì)外接口。
模塊之中,頂層的this關(guān)鍵字返回undefined,而不是指向window。也就是說,在模塊頂層使用this關(guān)鍵字,是無意義的。
同一個(gè)模塊如果加載多次,將只執(zhí)行一次。
Node.js加載
Node.js 對(duì) ES6 模塊的處理比較麻煩,因?yàn)樗凶约旱?CommonJS 模塊格式,與 ES6 模塊格式是不兼容的。
Node.js默認(rèn)是以CommonJS進(jìn)行加載的。
使用mjs后綴的話,Node.js會(huì)以ES6的模式加載。
使用cjs后綴的話,Node.js會(huì)以CommonJS模式加載。
package.json里面的type決定了默認(rèn)加載方式。
type = "module"/"commonjs"。
ES6模塊
創(chuàng)建一個(gè)模塊之后
在package.json文件中使用main/export指定模塊的入口文件
main字段
// ./node_modules/es-module-package/package.json
{
? "type": "module",
? "main": "./src/index.js"
}
import命令就可以加載這個(gè)模塊。
// ./my-app.mjs
import { something } from 'es-module-package';
export字段