?
Dieses Dokument verwendet PHP-Handbuch für chinesische Websites Freigeben
概述
使用ECMAScript 6的方法
數(shù)據(jù)類型
let命令
const命令
Set數(shù)據(jù)結構
Map數(shù)據(jù)結構
rest(...)運算符
遍歷器(Iterator)
generator 函數(shù)
原生對象的擴展
語法糖
二進制和八進制表示法
增強的對象寫法
箭頭函數(shù)(arrow)
函數(shù)參數(shù)的默認值
模板字符串
for...of循環(huán)
數(shù)組推導
多變量賦值
數(shù)據(jù)結構
class結構
module定義
ECMAScript 7
參考鏈接
ECMAScript 6 是JavaScript的下一代標準,正處在快速開發(fā)之中,大部分已經(jīng)完成了,預計將在2014年正式發(fā)布。Mozilla將在這個標準的基礎上,推出JavaScript 2.0。
ECMAScript 6的目標,是使得JavaScript可以用來編寫復雜的應用程序、函數(shù)庫和代碼的自動生成器(code generator)。
最新的瀏覽器已經(jīng)部分支持ECMAScript 6 的語法,可以通過《ECMAScript 6 瀏覽器兼容表》查看瀏覽器支持情況。
下面對ECMAScript 6新增的語法特性逐一介紹。由于ECMAScript 6的正式標準還未出臺,所以以下內(nèi)容隨時可能發(fā)生變化,不一定是最后的版本。
目前,V8引擎已經(jīng)部署了ECMAScript 6的部分特性。使用node.js 0.11版,就可以體驗這些特性。
node.js 0.11版的一種比較方便的使用方法,是使用版本管理工具nvm。下載nvm以后,進入項目目錄,運行下面的命令,激活nvm。
source nvm.sh
然后,指定node運行版本。
nvm use 0.11
最后,用--harmony參數(shù)進入node運行環(huán)境,就可以在命令行下體驗ECMAScript 6了。
node --harmony
另外,可以使用Google的Traceur(在線轉(zhuǎn)換工具),將ES6代碼編譯為ES5。
# 安裝 npm install -g traceur # 運行ES6文件 traceur /path/to/es6 # 將ES6文件轉(zhuǎn)為ES5文件 traceur --script /path/to/es6 --out /path/to/es5
(1)概述
ECMAScript 6新增了let命令,用來聲明變量。它的用法類似于var,但是所聲明的變量,只在let命令所在的代碼塊內(nèi)有效。
{ let a = 10; var b = 1; } a // ReferenceError: a is not defined. b //1
上面代碼在代碼塊之中,分別用let和var聲明了兩個變量。然后在代碼塊之外調(diào)用這兩個變量,結果let聲明的變量報錯,var聲明的變量返回了正確的值。這表明,let聲明的變量只在它所在的代碼塊有效。
下面的代碼如果使用var,最后輸出的是9。
var a = []; for (var i = 0; i < 10; i++) { var c = i; a[i] = function () { console.log(c); }; } a[6](); // 9
如果使用let,聲明的變量僅在塊級作用域內(nèi)有效,最后輸出的是6。
var a = []; for (var i = 0; i < 10; i++) { let c = i; a[i] = function () { console.log(c); }; } a[6](); // 6
注意,let不允許在相同作用域內(nèi),重復聲明同一個變量。
// 報錯 { let a = 10; var a = 1; } // 報錯 { let a = 10; let a = 1; }
(2)塊級作用域
let實際上為JavaScript新增了塊級作用域。
function f1() { let n = 5; if (true) { let n = 10; } console.log(n); // 5 }
上面的函數(shù)有兩個代碼塊,都聲明了變量n,運行后輸出5。這表示外層代碼塊不受內(nèi)層代碼塊的影響。如果使用var定義變量n,最后輸出的值就是10。
塊級作用域的出現(xiàn),實際上使得獲得廣泛應用的立即執(zhí)行函數(shù)(IIFE)不再必要了。
// IIFE寫法 (function () { var tmp = ...; ... }()); // 塊級作用域?qū)懛? { let tmp = ...; ... }
(3)不存在變量提升
需要注意的是,let聲明的變量不存在“變量提升”現(xiàn)象。
console.log(x); let x = 10;
上面代碼運行后會報錯,表示x沒有定義。如果用var聲明x,就不會報錯,輸出結果為undefined。
const也用來聲明變量,但是聲明的是常量。一旦聲明,常量的值就不能改變。
const PI = 3.1415; PI // 3.1415 PI = 3; PI // 3.1415 const PI = 3.1; PI // 3.1415
上面代碼表明改變常量的值是不起作用的。需要注意的是,對常量重新賦值不會報錯,只會默默地失敗。
const的作用域與var命令相同:如果在全局環(huán)境聲明,常量就在全局環(huán)境有效;如果在函數(shù)內(nèi)聲明,常量就在函數(shù)體內(nèi)有效。
ES6提供了新的數(shù)據(jù)結構Set。它類似于數(shù)組,但是成員的值都是唯一的,沒有重復的值。
Set本身是一個構造函數(shù),用來生成Set數(shù)據(jù)結構。
var s = new Set(); [2,3,5,4,5,2,2].map(x => s.add(x)) for (i of s) {console.log(i)} // 2 3 4 5
上面代碼表示,set數(shù)據(jù)結構不會添加重復的值。
set數(shù)據(jù)結構有以下屬性和方法:
size:返回成員總數(shù)。
add(value):添加某個值。
delete(value):刪除某個值。
has(value):返回一個布爾值,表示該值是否為set的成員。
clear():清除所有成員。
s.add("1").add("2").add("2"); // 注意“2”被加入了兩次 s.size // 2 s.has("1") // true s.has("2") // true s.has("3") // false s.delete("2"); s.has("2") // false
ES6還提供了map數(shù)據(jù)結構。它類似于對象,就是一個鍵值對的集合,但是“鍵”的范圍不限于字符串,甚至對象也可以當作鍵。
var m = new Map(); o = {p: "Hello World"}; m.set(o, "content") console.log(m.get(o)) // "content"
上面代碼將一個對象當作m的一個鍵。
Map數(shù)據(jù)結構有以下屬性和方法。
size:返回成員總數(shù)。
set(key, value):設置一個鍵值對。
get(key):讀取一個鍵。
has(key):返回一個布爾值,表示某個鍵是否在Map數(shù)據(jù)結構中。
delete(key):刪除某個鍵。
clear():清除所有成員。
var m = new Map(); m.set("edition", 6) // 鍵是字符串 m.set(262, "standard") // 鍵是數(shù)值 m.set(undefined, "nah") // 鍵是undefined var hello = function() {console.log("hello");} m.set(hello, "Hello ES6!") // 鍵是函數(shù) m.has("edition") // true m.has("years") // false m.has(262) // true m.has(undefined) // true m.has(hello) // true m.delete(undefined) m.has(undefined) // false m.get(hello) // Hello ES6! m.get("edition") // 6
(1)基本用法
ES6引入rest運算符(...),用于獲取函數(shù)的多余參數(shù),這樣就不需要使用arguments.length了。rest運算符后面是一個數(shù)組變量,該變量將多余的參數(shù)放入數(shù)組中。
function add(...values) { let sum = 0; for (var val of values) { sum += val; } return sum; } add(2, 5, 3) // 10
上面代碼的add函數(shù)是一個求和函數(shù),利用rest運算符,可以向該函數(shù)傳入任意數(shù)目的參數(shù)。
下面是一個利用rest運算符改寫數(shù)組push方法的例子。
function push(array, ...items) { items.forEach(function(item) { array.push(item); console.log(item); }); } var a = []; push(a, "a1", "a2", "a3", "a4");
(2)將數(shù)組轉(zhuǎn)為參數(shù)序列
rest運算符不僅可以用于函數(shù)定義,還可以用于函數(shù)調(diào)用。
function f(s1, s2, s3, s4, s5) { console.log(s1 + s2 + s3 + s4 +s5); } var a = ["a2", "a3", "a4", "a5"]; f("a1", ...a) // a1a2a3a4a5
從上面的例子可以看出,rest運算符的另一個重要作用是,可以將數(shù)組轉(zhuǎn)變成正常的參數(shù)序列。利用這一點,可以簡化求出一個數(shù)組最大元素的寫法。
// ES5 Math.max.apply(null, [14, 3, 77]) // ES6 Math.max(...[14, 3, 77]) // 等同于 Math.max(14, 3, 77);
上面代碼表示,由于JavaScript不提供求數(shù)組最大元素的函數(shù),所以只能套用Math.max函數(shù),將數(shù)組轉(zhuǎn)為一個參數(shù)序列,然后求最大值。有了rest運算符以后,就可以直接用Math.max了。
遍歷器(Iterator)是一種協(xié)議,任何對象都可以部署遍歷器協(xié)議,從而使得for...of循環(huán)可以遍歷這個對象。
遍歷器協(xié)議規(guī)定,任意對象只要部署了next方法,就可以作為遍歷器,但是next方法必須返回一個包含value和done兩個屬性的對象。其中,value屬性當前遍歷位置的值,done屬性是一個布爾值,表示遍歷是否結束。
function makeIterator(array){ var nextIndex = 0; return { next: function(){ return nextIndex < array.length ? {value: array[nextIndex++], done: false} : {done: true}; } } } var it = makeIterator(['a', 'b']); it.next().value // 'a' it.next().value // 'b' it.next().done // true
下面是一個無限運行的遍歷器的例子。
function idMaker(){ var index = 0; return { next: function(){ return {value: index++, done: false}; } } } var it = idMaker(); it.next().value // '0' it.next().value // '1' it.next().value // '2' // ...
上一部分的遍歷器,用來依次取出集合中的每一個成員,但是某些情況下,我們需要的是一個內(nèi)部狀態(tài)的遍歷器。也就是說,每調(diào)用一次遍歷器,對象的內(nèi)部狀態(tài)發(fā)生一次改變(可以理解成發(fā)生某些事件)。ECMAScript 6 引入了generator函數(shù),作用就是返回一個內(nèi)部狀態(tài)的遍歷器,主要特征是函數(shù)內(nèi)部使用了yield語句。
當調(diào)用generator函數(shù)的時候,該函數(shù)并不執(zhí)行,而是返回一個遍歷器(可以理解成暫停執(zhí)行)。以后,每次調(diào)用這個遍歷器的next方法,就從函數(shù)體的頭部或者上一次停下來的地方開始執(zhí)行(可以理解成恢復執(zhí)行),直到遇到下一個yield語句為止,并返回該yield語句的值。
ECMAScript 6草案定義的generator函數(shù),需要在function關鍵字后面,加一個星號。然后,函數(shù)內(nèi)部使用yield語句,定義遍歷器的每個成員。
function* helloWorldGenerator() { yield 'hello'; yield 'world'; }
yield有點類似于return語句,都能返回一個值。區(qū)別在于每次遇到y(tǒng)ield,函數(shù)返回緊跟在yield后面的那個表達式的值,然后暫停執(zhí)行,下一次從該位置繼續(xù)向后執(zhí)行,而return語句不具備位置記憶的功能。
上面代碼定義了一個generator函數(shù)helloWorldGenerator,它的遍歷器有兩個成員“hello”和“world”。調(diào)用這個函數(shù),就會得到遍歷器。
var hw = helloWorldGenerator();
執(zhí)行遍歷器的next方法,則會依次遍歷每個成員。
hw.next() // { value: 'hello', done: false } hw.next() // { value: 'world', done: false } hw.next() // { value: undefined, done: true } hw.next() // Error: Generator has already finished // at GeneratorFunctionPrototype.next (native) // at repl:1:3 // at REPLServer.defaultEval (repl.js:129:27) // ...
上面代碼一共調(diào)用了四次next方法。
第一次調(diào)用:函數(shù)開始執(zhí)行,直到遇到第一句yield語句為止。next方法返回一個對象,它的value屬性就是當前yield語句的值hello,done屬性的值false,表示遍歷還沒有結束。
第二次調(diào)用:函數(shù)從上次yield語句停下的地方,一直執(zhí)行到下一個yield語句。next方法返回一個對象,它的value屬性就是當前yield語句的值world,done屬性的值false,表示遍歷還沒有結束。
第三次調(diào)用:函數(shù)從上次yield語句停下的地方,一直執(zhí)行到函數(shù)結束。next方法返回一個對象,它的value屬性就是函數(shù)最后的返回值,由于上例的函數(shù)沒有return語句(即沒有返回值),所以value屬性的值為undefined,done屬性的值true,表示遍歷已經(jīng)結束。
第四次調(diào)用:由于此時函數(shù)已經(jīng)運行完畢,next方法直接拋出一個錯誤。
遍歷器的本質(zhì),其實是使用yield語句暫停執(zhí)行它后面的操作,當調(diào)用next方法時,再繼續(xù)往下執(zhí)行,直到遇到下一個yield語句,并返回該語句的值,如果直到運行結束。
如果next方法帶一個參數(shù),該參數(shù)就會被當作上一個yield語句的返回值。
function* f() { for(var i=0; true; i++) { var reset = yield i; if(reset) { i = -1; } } } var g = f(); g.next() // { value: 0, done: false } g.next() // { value: 1, done: false } g.next(true) // { value: 0, done: false }
上面代碼先定義了一個可以無限運行的generator函數(shù)f,如果next方法沒有參數(shù),正常情況下返回一個遞增的i;如果next方法有參數(shù),則上一次yield語句的返回值將會等于該參數(shù)。如果該參數(shù)為true,則會重置i的值。
generator函數(shù)的這種暫停執(zhí)行的效果,意味著可以把異步操作寫在yield語句里面,等到調(diào)用next方法時再往后執(zhí)行。這實際上等同于不需要寫回調(diào)函數(shù)了,因為異步操作的后續(xù)操作可以放在yield語句下面,反正要等到調(diào)用next方法時再執(zhí)行。所以,generator函數(shù)的一個重要實際意義就是用來處理異步操作,改寫回調(diào)函數(shù)。
function* loadUI() { showLoadingScreen(); yield loadUIDataAsynchronously(); hideLoadingScreen(); }
上面代碼表示,第一次調(diào)用loadUI函數(shù)時,該函數(shù)不會執(zhí)行,僅返回一個遍歷器。下一次對該遍歷器調(diào)用next方法,則會顯示登錄窗口,并且異步加載數(shù)據(jù)。再一次使用next方法,則會隱藏登錄窗口。可以看到,這種寫法的好處是所有登錄窗口的邏輯,都被封裝在一個函數(shù),按部就班非常清晰。
下面是一個利用generator函數(shù),實現(xiàn)斐波那契數(shù)列的例子。
function* fibonacci() { var previous = 0, current = 1; while (true) { var temp = previous; previous = current; current = temp + current; yield current; } } for (var i of fibonacci()) { console.log(i); } // 1, 2, 3, 5, 8, 13, ...,
下面是利用for...of語句,對斐波那契數(shù)列的另一種實現(xiàn)。
function* fibonacci() { let [prev, curr] = [0, 1]; for (;;) { [prev, curr] = [curr, prev + curr]; yield curr; } } for (n of fibonacci()) { if (n > 1000) break; console.log(n); }
從上面代碼可見,使用for...of語句時不需要使用next方法。
這里需要注意的是,yield語句運行的時候是同步運行,而不是異步運行(否則就失去了取代回調(diào)函數(shù)的設計目的了)。實際操作中,一般讓yield語句返回Promises對象。
var Q = require('q'); function delay(milliseconds) { var deferred = Q.defer(); setTimeout(deferred.resolve, milliseconds); return deferred.promise; } function *f(){ yield delay(100); };
上面代碼yield語句返回的就是一個Promises對象。
如果有一系列任務需要全部完成后,才能進行下一步操作,yield語句后面可以跟一個數(shù)組。下面就是一個例子。
function *f() { var urls = [ 'http://example.com/', 'http://twitter.com/', 'http://bbc.co.uk/news/' ]; var arrayOfPromises = urls.map(someOperation); var arrayOfResponses = yield arrayOfPromises; this.body = "Results"; for (var i = 0; i < urls.length; i++) { this.body += '\n' + urls[i] + ' response length is ' + arrayOfResponses[i].body.length; } };
ES6對JavaScript的原生對象,進行了擴展,提供了一系列新的屬性和方法。
Number.EPSILON Number.isInteger(Infinity) // false Number.isNaN("NaN") // false Math.acosh(3) // 1.762747174039086 Math.hypot(3, 4) // 5 Math.imul(Math.pow(2, 32) - 1, Math.pow(2, 32) - 2) // 2 "abcde".contains("cd") // true "abc".repeat(3) // "abcabcabc" Array.from(document.querySelectorAll('*')) // Returns a real Array Array.of(1, 2, 3) // Similar to new Array(...), but without special one-arg behavior [0, 0, 0].fill(7, 1) // [0,7,7] [1,2,3].findIndex(x => x == 2) // 1 ["a", "b", "c"].entries() // iterator [0, "a"], [1,"b"], [2,"c"] ["a", "b", "c"].keys() // iterator 0, 1, 2 ["a", "b", "c"].values() // iterator "a", "b", "c" Object.assign(Point, { origin: new Point(0,0) })
ECMAScript 6提供了很多JavaScript語法的便捷寫法。
ES6提供了二進制和八進制數(shù)值的新的寫法,分別用前綴0b和0o表示。
0b111110111 === 503 // true0o767 === 503 // true
ES6允許直接寫入變量和函數(shù),作為對象的屬性和方法。這樣的書寫更加簡潔。
var Person = { name: '張三', //等同于birth: birth birth, // 等同于hello: function ()... hello() { console.log('我的名字是', this.name); } };
(1)定義
ES6允許使用“箭頭”(=>)定義函數(shù)。
var f = v => v;
上面的箭頭函數(shù)等同于:
var f = function(v) { return v; };
如果箭頭函數(shù)不需要參數(shù)或需要多個參數(shù),就使用一個圓括號代表參數(shù)部分。
var f = () => 5; // 等同于 var f = function (){ return 5 }; var sum = (num1, num2) => num1 + num2; // 等同于 var sum = function(num1, num2) { return num1 + num2; };
如果箭頭函數(shù)的代碼塊部分多于一條語句,就要使用大括號將它們括起來,并且使用return語句返回。
var sum = (num1, num2) => { return num1 + num2; }
由于大括號被解釋為代碼塊,所以如果箭頭函數(shù)直接返回一個對象,必須在對象外面加上括號。
var getTempItem = id => ({ id: id, name: "Temp" });
(2)實例:回調(diào)函數(shù)的簡化
箭頭函數(shù)的一個用處是簡化回調(diào)函數(shù)。
// 正常函數(shù)寫法 [1,2,3].map(function (x) { return x * x; }); // 箭頭函數(shù)寫法 [1,2,3].map(x => x * x);
另一個例子是
// 正常函數(shù)寫法 var result = values.sort(function(a, b) { return a - b; }); // 箭頭函數(shù)寫法 var result = values.sort((a, b) => a - b);
(3)注意點
箭頭函數(shù)有幾個使用注意點。
函數(shù)體內(nèi)的this對象,綁定定義時所在的對象,而不是使用時所在的對象。
不可以當作構造函數(shù),也就是說,不可以使用new命令,否則會拋出一個錯誤。
不可以使用arguments對象,該對象在函數(shù)體內(nèi)不存在。
關于this對象,下面的代碼將它綁定定義時的對象。
var handler = { id: "123456", init: function() { document.addEventListener("click", event => this.doSomething(event.type), false); }, doSomething: function(type) { console.log("Handling " + type + " for " + this.id); } };
上面代碼的init和doSomething方法中,都使用了箭頭函數(shù),它們中的this都綁定handler對象。否則,doSomething方法內(nèi)部的this對象就指向全局對象,運行時會報錯。
ECMAScript 6 允許為函數(shù)的參數(shù)設置默認值。
function Point(x = 0, y = 0) { this.x = x; this.y = y; } var p = new Point(); // p = { x:0, y:0 }
模板字符串(template string)是增強版的字符串,即可以當作普通字符串使用,也可以在字符串中嵌入變量。它用反引號(`)標識。
// 普通字符串 `In JavaScript '\n' is a line-feed.` // 多行字符串 `In JavaScript this is not legal.` // 字符串中嵌入變量 var name = "Bob", time = "today"; `Hello ${name}, how are you ${time}?` var x = 1; var y = 2; console.log(`${ x } + ${ y } = ${ x + y}`) // "1 + 2 = 3"
JavaScript原有的for...in循環(huán),只能獲得對象的鍵名,不能直接獲取鍵值。ES6提供for...of循環(huán),允許遍歷獲得鍵值。
var arr = ["a", "b", "c", "d"]; for (a in arr) { console.log(a); } // 0 // 1 // 2 // 3 for (a of arr) { console.log(a); } // a // b // c // d
上面代碼表明,for...in循環(huán)讀取鍵名,for...of循環(huán)讀取鍵值。
for...of循環(huán)還可以遍歷對象。
var es6 = { edition: 6, committee: "TC39", standard: "ECMA-262" }; for (e in es6) { console.log(e); } // edition // committee // standard var engines = Set(["Gecko", "Trident", "Webkit", "Webkit"]); for (var e of engines) { console.log(e); } // Gecko // Trident // Webkit var es6 = new Map(); es6.set("edition", 6); es6.set("committee", "TC39"); es6.set("standard", "ECMA-262"); for (var [name, value] of es6) { console.log(name + ": " + value); } // edition: 6 // committee: TC39 // standard: ECMA-262
上面代碼一共包含三個例子,第一個是for...in循環(huán)的例子,后兩個是for...of循環(huán)的例子。最后一個例子是同時遍歷對象的鍵名和鍵值。
(1)基本用法
ES6提供簡潔寫法,允許直接通過現(xiàn)有數(shù)組生成新數(shù)組,這被稱為數(shù)組推導(array comprehension)。
var a1 = [1, 2, 3, 4]; var a2 = [i * 2 for (i of a1)]; a2 // [2, 4, 6, 8]
上面代碼表示,通過for...of結構,數(shù)組a2直接在a1的基礎上生成。
數(shù)組推導可以替代map和filter方法。
[for (i of [1, 2, 3]) i * i]; // 等價于 [1, 2, 3].map(function (i) { return i * i }); [i for (i of [1,4,2,3,-8]) if (i < 3)]; // 等價于 [1,4,2,3,-8].filter(function(i) { return i < 3 });
上面代碼說明,模擬map功能只要單純的for...of循環(huán)就行了,模擬filter功能除了for...of循環(huán),還必須加上if語句。
(2)多重推導
新引入的for...of結構,可以直接跟在表達式的前面或后面,甚至可以在一個數(shù)組推導中,使用多個for...of結構。
var a1 = ["x1", "y1"]; var a2 = ["x2", "y2"]; var a3 = ["x3", "y3"]; [(console.log(s + w + r)) for (s of a1) for (w of a2) for (r of a3)]; // x1x2x3 // x1x2y3 // x1y2x3 // x1y2y3 // y1x2x3 // y1x2y3 // y1y2x3 // y1y2y3
上面代碼在一個數(shù)組推導之中,使用了三個for...of結構。
需要注意的是,數(shù)組推導的方括號構成了一個單獨的作用域,在這個方括號中聲明的變量類似于使用let語句聲明的變量。
(3)字符串推導
由于字符串可以視為數(shù)組,因此字符串也可以直接用于數(shù)組推導。
[c for (c of 'abcde') if (/[aeiou]/.test(c))].join('') // 'ae' [c+'0' for (c of 'abcde')].join('') // 'a0b0c0d0e0'
上面代碼使用了數(shù)組推導,對字符串進行處理。
上一部分的數(shù)組推導有一個缺點,就是新數(shù)組會立即在內(nèi)存中生成。這時,如果原數(shù)組是一個很大的數(shù)組,將會非常耗費內(nèi)存。
ES6允許簡潔地對多變量賦值。正常情況下,將數(shù)組元素賦值給多個變量,只能一次次分開賦值。
var a = 1; var b = 2; var c = 3;
ES6允許寫成下面這樣。
var [a, b, c] = [1, 2, 3];
本質(zhì)上,這種寫法屬于模式匹配,只要等號兩邊的模式相同,左邊的變量就會被賦予對應的值。下面是一些嵌套數(shù)組的例子。
var [foo, [[bar], baz]] = [1, [[2], 3]] var [,,third] = ["foo", "bar", "baz"] var [head, ...tail] = [1, 2, 3, 4]
它還可以接受默認值。
var [missing = true] = []; console.log(missing) // true var { x = 3 } = {}; console.log(x) // 3
它不僅可以用于數(shù)組,還可以用于對象。
var { foo, bar } = { foo: "lorem", bar: "ipsum" }; foo // "lorem" bar // "ipsum" var o = { p1: [ "Hello", { p2: "World" } ] }; var { a: [p1, { p2 }] } = o; console.log(p1) // "Hello" console.log(p2) // "World"
這種寫法的用途很多。
(1)交換變量的值。
[x, y] = [y, x];
(2)從函數(shù)返回多個值。
function example() { return [1, 2, 3]; } var [a, b, c] = example();
(3)函數(shù)參數(shù)的定義。
function f({p1, p2, p3}) { // ... }
(4)函數(shù)參數(shù)的默認值。
jQuery.ajax = function (url, { async = true, beforeSend = function () {}, cache = true, complete = function () {}, crossDomain = false, global = true, // ... more config }) { // ... do stuff };
(1)基本用法
ES6提供了“類”(class)。此前,一般用構造函數(shù)模擬“類”。
// ES5 var Language = function(config) { this.name = config.name; this.founder = config.founder; this.year = config.year; }; Language.prototype.summary = function() { return this.name+"由"+this.founder+"在"+this.year+"創(chuàng)造"; }; // ES6 class Language { constructor(name, founder, year) { this.name = name; this.founder = founder; this.year = year; } summary() { return this.name+"由"+this.founder+"在"+this.year+"創(chuàng)造"; } }
在上面代碼中,ES6用constructor方法,代替ES5的構造函數(shù)。
(2)繼承
ES6的class結構還允許使用extends關鍵字,表示繼承。
class MetaLanguage extends Language { constructor(x, y, z, version) { super(x, y, z); this.version = version; } summary() { //... super.summary(); } }
上面代碼的super方法,表示調(diào)用父類的構造函數(shù)。
(1)基本用法
ES6允許定義模塊。也就是說,允許一個JavaScript腳本文件調(diào)用另一個腳本文件。
假設有一個circle.js,它是一個單獨模塊。
// circle.js export function area(radius) { return Math.PI * radius * radius; } export function circumference(radius) { return 2 * Math.PI * radius; }
然后,main.js引用這個模塊。
// main.js import { area, circumference } from 'circle'; console.log("圓面積:" + area(4)); console.log("圓周長:" + circumference(14));
另一種寫法是整體加載circle.js。
// main.jsmodule circle from 'circle'; console.log("圓面積:" + circle.area(4)); console.log("圓周長:" + circle.circumference(14));
(2)模塊的繼承
一個模塊也可以繼承另一個模塊。
// circleplus.js export * from 'circle'; export var e = 2.71828182846; export default function(x) { return Math.exp(x); }
加載上面的模塊。
// main.js module math from "circleplus"; import exp from "circleplus"; console.log(exp(math.pi);
(3)模塊的默認方法
還可以為模塊定義默認方法。
// circleplus.js export default function(x) { return Math.exp(x); }
2013年3月,ECMAScript 6的草案封閉,不再接受新功能了。新的功能將被加入ECMAScript 7。根據(jù)JavaScript創(chuàng)造者Brendan Eich的設想,ECMAScript 7將使得JavaScript更適于開發(fā)復雜的應用程序和函數(shù)庫。
ECMAScript 7可能包括的功能有:
Object.observe:對象與網(wǎng)頁元素的雙向綁定,只要其中之一發(fā)生變化,就會自動反映在另一者上。
Multi-Threading:多線程支持。目前,Intel和Mozilla有一個共同的研究項目RiverTrail,致力于讓JavaScript多線程運行。預計這個項目的研究成果會被納入ECMAScript標準。
Traits:它將是“類”功能(class)的一個替代。通過它,不同的對象可以分享同樣的特性。
其他可能包括的功能還有:更精確的數(shù)值計算、改善的內(nèi)存回收、增強的跨站點安全、類型化的更貼近硬件的(Typed, Low-level)操作、國際化支持(Internationalization Support)、更多的數(shù)據(jù)結構等等。
Sayanee Basu, Use ECMAScript 6 Today
Ariya Hidayat, Toward Modern Web Apps with ECMAScript 6
Nick Fitzgerald, Destructuring Assignment in ECMAScript 6
jmar777, What's the Big Deal with Generators?
Nicholas C. Zakas, Understanding ECMAScript 6 arrow functions
Dale Schouten, 10 Ecmascript-6 tricks you can perform right now
Mozilla Developer Network, Iterators and generators
Steven Sanderson, Experiments with Koa and JavaScript Generators
Matt Baker, Replacing callbacks with ES6 Generators
Domenic Denicola, ES6: The Awesome Parts
Casper Beyer, ECMAScript 6 Features and Tools
Luke Hoban, ES6 features