感謝社區(qū)中各位的大力支持,譯者再次奉上一點(diǎn)點(diǎn)福利:阿里云產(chǎn)品券比驻,享受所有官網(wǎng)優(yōu)惠棋蚌,并抽取幸運(yùn)大獎(jiǎng):點(diǎn)擊這里領(lǐng)取
在本書寫作的時(shí)候,ES6(ECMAScript 2015)的最終草案即將為了ECMA的批準(zhǔn)而進(jìn)行最終的官方投票璃诀。但即便是在ES6已經(jīng)被最終定稿的時(shí)候攀芯,TC39協(xié)會(huì)已經(jīng)在為了ES7/2016和將來的特性進(jìn)行努力的工作。
正如我們?cè)诘谝徽轮杏懻撨^的文虏,預(yù)計(jì)JS進(jìn)化的節(jié)奏將會(huì)從好幾年升級(jí)一次加速到每年進(jìn)行一次官方的版本升級(jí)(因此采用編年命名法)。這將會(huì)徹底改變JS開發(fā)者學(xué)習(xí)與跟上這門語言腳步的方式殖演。
但更重要的是氧秘,協(xié)會(huì)實(shí)際上將會(huì)一個(gè)特性一個(gè)特性地進(jìn)行工作。只要一種特性的規(guī)范被定義完成趴久,而且通過在幾種瀏覽器中的實(shí)驗(yàn)性實(shí)現(xiàn)打通了關(guān)節(jié)丸相,那么這種特性就會(huì)被認(rèn)為足夠穩(wěn)定并可以開始使用了。我們都被強(qiáng)烈鼓勵(lì)一旦特性準(zhǔn)備好就立即采用它彼棍,而不是等待什么官方標(biāo)準(zhǔn)投票灭忠。如果你還沒學(xué)過ES6膳算,現(xiàn)在上船的日子已經(jīng)過了室埋!
在本書寫作時(shí)鞍爱,一個(gè)未來特性提案的列表和它們的狀態(tài)可以在這里看到(https://github.com/tc39/ecma262#current-proposals)。
在所有我們支持的瀏覽器實(shí)現(xiàn)這些新特性之前皿哨,轉(zhuǎn)譯器和填補(bǔ)是我們?nèi)绾螛蚪铀鼈兊姆椒ㄓ沉铡abel机隙,Traceur,和其他幾種主流轉(zhuǎn)譯器已經(jīng)支持了一些最可能穩(wěn)定下來的ES6之后的特性萨西。
認(rèn)識(shí)到這一點(diǎn)有鹿,是時(shí)候看一看它們之中的一些了。讓我們開始吧谎脯!
警告: 這些特性都處于開發(fā)的各種階段葱跋。雖然它們很可能確定下來,而且將與本章的內(nèi)容看起來相似源梭,但還是要抱著更多質(zhì)疑的態(tài)度看待本章的內(nèi)容娱俺。這一章將會(huì)在本書未來的版本中隨著這些(和其他的!)特性的確定而演化咸产。
async function
我們?cè)诘谒恼碌摹癎enerators + Promises”中提到過矢否,generatoryield
一個(gè)promise給一個(gè)類似運(yùn)行器的工具,它會(huì)在promise完成時(shí)推進(jìn)generator —— 有一個(gè)提案是要為這種模式提供直接的語法支持脑溢。讓我們簡(jiǎn)要看一下這個(gè)被提出的特性僵朗,它稱為async function
。
回想一下第四章中的這個(gè)generator的例子:
run( function *main() {
var ret = yield step1();
try {
ret = yield step2( ret );
}
catch (err) {
ret = yield step2Failed( err );
}
ret = yield Promise.all([
step3a( ret ),
step3b( ret ),
step3c( ret )
]);
yield step4( ret );
} )
.then(
function fulfilled(){
// `*main()` 成功地完成了
},
function rejected(reason){
// 噢屑彻,什么東西搞錯(cuò)了
}
);
被提案的async function
語法可以無需run(..)
工具就表達(dá)相同的流程控制邏輯验庙,因?yàn)镴S將會(huì)自動(dòng)地知道如何尋找promise來等待和推進(jìn)∩缟考慮如下代碼:
async function main() {
var ret = await step1();
try {
ret = await step2( ret );
}
catch (err) {
ret = await step2Failed( err );
}
ret = await Promise.all( [
step3a( ret ),
step3b( ret ),
step3c( ret )
] );
await step4( ret );
}
main()
.then(
function fulfilled(){
// `main()` 成功地完成了
},
function rejected(reason){
// 噢粪薛,什么東西搞錯(cuò)了
}
);
取代function *main() { ..
聲明的,是我們使用async function main() { ..
形式聲明搏恤。而取代yield
一個(gè)promise的违寿,是我們await
這個(gè)promise。運(yùn)行main()
函數(shù)的調(diào)用實(shí)際上返回一個(gè)我們可以直接監(jiān)聽的promise熟空。這與我們從一個(gè)run(main)
調(diào)用中拿回一個(gè)promise是等價(jià)的藤巢。
你看到對(duì)稱性了嗎?async function
實(shí)質(zhì)上是 generators + promises + run(..)
模式的語法糖息罗;它們?cè)诘讓拥牟僮魇窍嗤模?/p>
如果你是一個(gè)C#開發(fā)者而且這種async
/await
看起來很熟悉掂咒,那是因?yàn)檫@種特性就是直接由C#的特性啟發(fā)的。看到語言提供一致性是一件好事绍刮!
Babel温圆、Traceur 以及其他轉(zhuǎn)譯器已經(jīng)對(duì)當(dāng)前的async function
狀態(tài)有了早期支持,所以你已經(jīng)可以使用它們了孩革。但是岁歉,在下一節(jié)的“警告”中,我們將看到為什么你也許還不應(yīng)該上這艘船嫉戚。
注意: 還有一個(gè)async function*
的提案刨裆,它應(yīng)當(dāng)被稱為“異步generator”。你可以在同一段代碼中使用yield
和await
兩者彬檀,甚至是在同一個(gè)語句中組合這兩個(gè)操作:x = await yield y
帆啃。“異步generator”提案看起來更具變化 —— 也就是說窍帝,它返回一個(gè)沒有還沒有完全被計(jì)算好的值努潘。一些人覺得它應(yīng)當(dāng)是一個(gè) 可監(jiān)聽對(duì)象(observable),有些像是一個(gè)迭代器和promise的組合坤学。就目前來說疯坤,我們不會(huì)進(jìn)一步探討這個(gè)話題,但是會(huì)繼續(xù)關(guān)注它的演變深浮。
警告
關(guān)于async function
的一個(gè)未解的爭(zhēng)論點(diǎn)是压怠,因?yàn)樗鼉H返回一個(gè)promise,所以沒有辦法從外部 撤銷 一個(gè)當(dāng)前正在運(yùn)行的async function
實(shí)例飞苇。如果這個(gè)異步操作是資源密集型的菌瘫,而且你想在自己確定不需要它的結(jié)果時(shí)能立即釋放資源,這可能是一個(gè)問題布卡。
舉例來說:
async function request(url) {
var resp = await (
new Promise( function(resolve,reject){
var xhr = new XMLHttpRequest();
xhr.open( "GET", url );
xhr.onreadystatechange = function(){
if (xhr.readyState == 4) {
if (xhr.status == 200) {
resolve( xhr );
}
else {
reject( xhr.statusText );
}
}
};
xhr.send();
} )
);
return resp.responseText;
}
var pr = request( "http://some.url.1" );
pr.then(
function fulfilled(responseText){
// ajax 成功
},
function rejected(reason){
// 噢雨让,什么東西搞錯(cuò)了
}
);
我構(gòu)想的request(..)
有點(diǎn)兒像最近被提案要包含進(jìn)web平臺(tái)的fetch(..)
工具。我們關(guān)心的是忿等,例如栖忠,如果你想要用pr
值以某種方法指示撤銷一個(gè)長(zhǎng)時(shí)間運(yùn)行的Ajax請(qǐng)求會(huì)怎么樣?
Promise是不可撤銷的(在本書寫作時(shí))贸街。在我和其他許多人看來庵寞,它們就不應(yīng)該是可以被撤銷的(參見本系列的 異步與性能)。而且即使一個(gè)proimse確實(shí)擁有一個(gè)cancel()
方法薛匪,那么一定意味著調(diào)用pr.cancel()
應(yīng)當(dāng)真的沿著promise鏈一路傳播一個(gè)撤銷信號(hào)到async function
嗎捐川?
對(duì)于這個(gè)爭(zhēng)論的幾種可能的解決方案已經(jīng)浮出水面:
-
async function
將根本不能被撤銷(現(xiàn)狀) - 一個(gè)“撤銷存根”可以在調(diào)用時(shí)傳遞給一個(gè)異步函數(shù)
- 將返回值改變?yōu)橐粋€(gè)新增的可撤銷promsie類型
- 將返回值改變?yōu)榉莗romise的其他東西(比如,可監(jiān)聽對(duì)象蛋辈,或帶有promise和撤銷能力的控制存根)
在本書寫作時(shí),async function
返回普通的promise,所以完全改變返回值不太可能冷溶。但是現(xiàn)在下定論還是為時(shí)過早了渐白。讓我們持續(xù)關(guān)注這個(gè)討論吧。
Object.observe(..)
前端web開發(fā)的圣杯之一就是數(shù)據(jù)綁定 —— 監(jiān)聽一個(gè)數(shù)據(jù)對(duì)象的更新并同步這個(gè)數(shù)據(jù)的DOM表現(xiàn)形式逞频。大多數(shù)JS框架都為這些類型的操作提供某種機(jī)制纯衍。
在ES6后期,我們似乎很有可能看到這門語言通過一個(gè)稱為Object.observe(..)
的工具苗胀,對(duì)此提供直接的支持襟诸。實(shí)質(zhì)上,它的思想是你可以建立監(jiān)聽器來監(jiān)聽一個(gè)對(duì)象的變化基协,并在一個(gè)變化發(fā)生的任何時(shí)候調(diào)用一個(gè)回調(diào)歌亲。例如,你可相應(yīng)地更新DOM澜驮。
你可以監(jiān)聽六種類型的變化:
- add
- update
- delete
- reconfigure
- setPrototype
- preventExtensions
默認(rèn)情況下陷揪,你將會(huì)收到所有這些類型的變化的通知,但是你可以將它們過濾為你關(guān)心的那一些杂穷。
考慮如下代碼:
var obj = { a: 1, b: 2 };
Object.observe(
obj,
function(changes){
for (var change of changes) {
console.log( change );
}
},
[ "add", "update", "delete" ]
);
obj.c = 3;
// { name: "c", object: obj, type: "add" }
obj.a = 42;
// { name: "a", object: obj, type: "update", oldValue: 1 }
delete obj.b;
// { name: "b", object: obj, type: "delete", oldValue: 2 }
除了主要的"add"
悍缠、"update"
、和"delete"
變化類型:
"reconfigure"
變化事件在對(duì)象的一個(gè)屬性通過Object.defineProperty(..)
而重新配置時(shí)觸發(fā)耐量,比如改變它的writable
屬性飞蚓。更多信息參見本系列的 this與對(duì)象原型。-
"preventExtensions"
變化事件在對(duì)象通過Object.preventExtensions(..)
被設(shè)置為不可擴(kuò)展時(shí)觸發(fā)廊蜒。因?yàn)?code>Object.seal(..)和
Object.freeze(..)
兩者都暗示著Object.preventExtensions(..)
趴拧,所以它們也將觸發(fā)相應(yīng)的變化事件。另外劲藐,"reconfigure"
變化事件也會(huì)為對(duì)象上的每個(gè)屬性被觸發(fā)八堡。 "setPrototype"
變化事件在一個(gè)對(duì)象的[[Prototype]]
被改變時(shí)觸發(fā),不論是使用__proto__
setter聘芜,還是使用Object.setPrototypeOf(..)
設(shè)置它兄渺。
注意,這些變化事件在會(huì)在變化發(fā)生后立即觸發(fā)汰现。不要將它們與代理(見第七章)搞混挂谍,代理是可以在動(dòng)作發(fā)生之前攔截它們的。對(duì)象監(jiān)聽讓你在變化(或一組變化)發(fā)生之后進(jìn)行應(yīng)答瞎饲。
自定義變化事件
除了六種內(nèi)建的變化事件類型口叙,你還可以監(jiān)聽并觸發(fā)自定義變化事件。
考慮如下代碼:
function observer(changes){
for (var change of changes) {
if (change.type == "recalc") {
change.object.c =
change.object.oldValue +
change.object.a +
change.object.b;
}
}
}
function changeObj(a,b) {
var notifier = Object.getNotifier( obj );
obj.a = a * 2;
obj.b = b * 3;
// queue up change events into a set
notifier.notify( {
type: "recalc",
name: "c",
oldValue: obj.c
} );
}
var obj = { a: 1, b: 2, c: 3 };
Object.observe(
obj,
observer,
["recalc"]
);
changeObj( 3, 11 );
obj.a; // 12
obj.b; // 30
obj.c; // 3
變化的集合("recalc"
自定義事件)為了投遞給監(jiān)聽器而被排隊(duì)嗅战,但還沒被投遞妄田,這就是為什么obj.c
依然是3
俺亮。
默認(rèn)情況下,這些變化將在當(dāng)前事件輪詢(參見本系列的 異步與性能)的末尾被投遞疟呐。如果你想要立即投遞它們脚曾,使用Object.deliverChangeRecords(observer)
。一旦這些變化投遞完成启具,你就可以觀察到obj.c
如預(yù)期地更新為:
obj.c; // 42
在前面的例子中本讥,我們使用變化完成事件的記錄調(diào)用了notifier.notify(..)
。將變化事件的記錄進(jìn)行排隊(duì)的一種替代形式是使用performChange(..)
鲁冯,它把事件的類型與事件記錄的屬性(通過一個(gè)函數(shù)回調(diào))分割開來拷沸。考慮如下代碼:
notifier.performChange( "recalc", function(){
return {
name: "c",
// `this` 是被監(jiān)聽的對(duì)象
oldValue: this.c
};
} );
在特定的環(huán)境下薯演,這種關(guān)注點(diǎn)分離可能與你的使用模式匹配的更干凈撞芍。
中止監(jiān)聽
正如普通的事件監(jiān)聽器一樣,你可能希望停止監(jiān)聽一個(gè)對(duì)象的變化事件涣仿。為此勤庐,你可以使用Object.unobserve(..)
。
舉例來說:
var obj = { a: 1, b: 2 };
Object.observe( obj, function observer(changes) {
for (var change of changes) {
if (change.type == "setPrototype") {
Object.unobserve(
change.object, observer
);
break;
}
}
} );
在這個(gè)小例子中好港,我們監(jiān)聽變化事件直到我們看到"setPrototype"
事件到來愉镰,那時(shí)我們就不再監(jiān)聽任何變化事件了。
指數(shù)操作符
為了使JavaScript以與Math.pow(..)
相同的方式進(jìn)行指數(shù)運(yùn)算钧汹,有一個(gè)操作符被提出了丈探。考慮如下代碼:
var a = 2;
a ** 4; // Math.pow( a, 4 ) == 16
a **= 3; // a = Math.pow( a, 3 )
a; // 8
注意: **
實(shí)質(zhì)上在Python拔莱、Ruby碗降、Perl、和其他語言中都與此相同塘秦。
對(duì)象屬性與 ...
正如我們?cè)诘诙碌摹疤嗨显ǎ伲线m”一節(jié)中看到的尊剔,...
操作符在擴(kuò)散或收集一個(gè)數(shù)組上的工作方式是顯而易見的爪幻。但對(duì)象會(huì)怎么樣?
這樣的特性在ES6中被考慮過须误,但是被推遲到ES6之后(也就是“ES7”或者“ES2016”或者……)了挨稿。這是它在“ES6以后”的時(shí)代中可能的工作方式:
var o1 = { a: 1, b: 2 },
o2 = { c: 3 },
o3 = { ...o1, ...o2, d: 4 };
console.log( o3.a, o3.b, o3.c, o3.d );
// 1 2 3 4
...
操作符也可能被用于將一個(gè)對(duì)象的被解構(gòu)屬性收集到另一個(gè)對(duì)象:
var o1 = { b: 2, c: 3, d: 4 };
var { b, ...o2 } = o1;
console.log( b, o2.c, o2.d ); // 2 3 4
這里,...o2
將被解構(gòu)的c
和d
屬性重新收集到一個(gè)o2
對(duì)象中(與o1
不同京痢,o2
沒有b
屬性)奶甘。
重申一下,這些只是正在考慮之中的ES6之后的提案祭椰。但是如果它們能被確定下來就太酷了臭家。
Array#includes(..)
JS開發(fā)者需要執(zhí)行的極其常見的一個(gè)任務(wù)就是在一個(gè)值的數(shù)組中搜索一個(gè)值疲陕。完成這項(xiàng)任務(wù)的方式曾經(jīng)總是:
var vals = [ "foo", "bar", 42, "baz" ];
if (vals.indexOf( 42 ) >= 0) {
// 找到了!
}
進(jìn)行>= 0
檢查是因?yàn)?code>indexOf(..)在找到結(jié)果時(shí)返回一個(gè)0
或更大的數(shù)字值钉赁,或者在沒找到結(jié)果時(shí)返回-1
鸭轮。換句話說,我們?cè)谝粋€(gè)布爾值的上下文環(huán)境中使用了一個(gè)返回索引的函數(shù)橄霉。而由于-1
是truthy而非falsy,所以我們不得不手動(dòng)進(jìn)行檢查邑蒋。
在本系列的 類型與文法 中姓蜂,我探索了另一種我稍稍偏好的模式:
var vals = [ "foo", "bar", 42, "baz" ];
if (~vals.indexOf( 42 )) {
// 找到了!
}
這里的~
操作符使indexOf(..)
的返回值與一個(gè)值的范圍相一致医吊,這個(gè)范圍可以恰當(dāng)?shù)貜?qiáng)制轉(zhuǎn)換為布爾型钱慢。也就是,-1
產(chǎn)生0
(falsy)卿堂,而其余的東西產(chǎn)生非零值(truthy)束莫,而這正是我們判定是否找到值的依據(jù)。
雖然我覺得這是一種改進(jìn)草描,但有另一些人強(qiáng)烈反對(duì)览绿。然而,沒有人會(huì)質(zhì)疑indexOf(..)
的檢索邏輯是完美的穗慕。例如饿敲,在數(shù)組中查找NaN
值會(huì)失敗。
于是一個(gè)提案浮出了水面并得到了大量的支持 —— 增加一個(gè)真正的返回布爾值的數(shù)組檢索方法逛绵,稱為includes(..)
:
var vals = [ "foo", "bar", 42, "baz" ];
if (vals.includes( 42 )) {
// 找到了怀各!
}
注意: Array#includes(..)
使用了將會(huì)找到NaN
值的匹配邏輯,但將不會(huì)區(qū)分-0
與0
(參見本系列的 類型與文法)术浪。如果你在自己的程序中不關(guān)心-0
值瓢对,那么它很可能正是你希望的。如果你 確實(shí) 關(guān)心-0
胰苏,那么你就需要實(shí)現(xiàn)你自己的檢索邏輯硕蛹,很可能是使用Object.is(..)
工具(見六章)。
SIMD
我們?cè)诒鞠盗械?異步與性能 中詳細(xì)講解了一個(gè)指令碟联,多個(gè)數(shù)據(jù)(SIMD)妓美,但因?yàn)樗俏磥鞪S中下一個(gè)很可能被確定下來的特性,所以這里簡(jiǎn)要地提一下鲤孵。
SIMD API 暴露了各種底層(CPU)指令壶栋,它們可以同時(shí)操作一個(gè)以上的數(shù)字值。例如普监,你可以指定兩個(gè)擁有4個(gè)或8個(gè)數(shù)字的 向量贵试,然后一次性分別相乘所有元素(數(shù)據(jù)并行機(jī)制A鸲怠)。
考慮如下代碼:
var v1 = SIMD.float32x4( 3.14159, 21.0, 32.3, 55.55 );
var v2 = SIMD.float32x4( 2.1, 3.2, 4.3, 5.4 );
SIMD.float32x4.mul( v1, v2 );
// [ 6.597339, 67.2, 138.89, 299.97 ]
SIMD將會(huì)引入mul(..)
(乘法)之外的幾種其他操作毙玻,比如sub()
豌蟋、div()
、abs()
桑滩、neg()
梧疲、sqrt()
、以及其他許多运准。
并行數(shù)學(xué)操作對(duì)下一代的高性能JS應(yīng)用程序至關(guān)重要幌氮。
WebAssembly (WASM)
在本書的第一版將近完成的時(shí)候,Brendan Eich 突然宣布了一個(gè)有可能對(duì)JavaScript未來的道路產(chǎn)生重大沖擊的公告:WebAssembly(WASM)胁澳。我們不能在這里詳細(xì)地探討WASM该互,因?yàn)樵诒緯鴮懽鲿r(shí)這個(gè)話題為時(shí)過早了。但如果不簡(jiǎn)要地提上一句韭畸,這本書就不夠完整宇智。
JS語言在近期(和近未來的)設(shè)計(jì)的改變上所承受的最大壓力之一,就是渴望它能夠成為從其他語言(比如 C/C++胰丁,ClojureScript随橘,等等)轉(zhuǎn)譯/交叉編譯來的、合適的目標(biāo)語言锦庸。顯然太防,作為JavaScript運(yùn)行的代碼性能是一個(gè)主要問題。
正如在本系列的 異步與性能 中討論過的酸员,幾年前一組在Mozilla的開發(fā)者給JavaScript引入了一個(gè)稱為ASM.js的想法蜒车。AMS.js是一個(gè)合法JS的子集,它大幅地制約了使代碼難于被JS引擎優(yōu)化的特定行為幔嗦。其結(jié)果就是兼容AMS.js的代碼在一個(gè)支持ASM的引擎上可以顯著地快速運(yùn)行酿愧,幾乎可以與優(yōu)化過的原生C語言的等價(jià)物相媲美。許多觀點(diǎn)認(rèn)為邀泉,對(duì)于那些將要由JavaScript編寫的渴求性能的應(yīng)用程序來說嬉挡,ASM.js很可能將是它們的基干。
換言之汇恤,在瀏覽器中條條大路通過JavaScript通向運(yùn)行的代碼庞钢。
直到WASM公告之前,是這樣的因谎。WASM提供了另一條路線基括,讓其他語言不必非得首先通過JavaScript就能將瀏覽器的運(yùn)行時(shí)環(huán)境作為運(yùn)行的目標(biāo)。實(shí)質(zhì)上财岔,如果WASM啟用风皿,JS引擎將會(huì)生長(zhǎng)出額外的能力 —— 執(zhí)行可以被視為有些與字節(jié)碼相似的二進(jìn)制代碼(就像在JVM上運(yùn)行的那些東西)河爹。
WASM提出了一種高度壓縮的代碼AST(語法樹)的二進(jìn)制表示格式,它可以繼而像JS引擎以及它的基礎(chǔ)結(jié)構(gòu)直接發(fā)出指令桐款,無需被JS解析咸这,甚至無需按照J(rèn)S的規(guī)則動(dòng)作。像C或C++這樣的語言可以直接被編譯為WASM格式而非ASM.js魔眨,并且由于跳過JS解析而得到額外的速度優(yōu)勢(shì)媳维。
短期內(nèi),WASM與AMS.js遏暴、JS不相上下侨艾。但是最終,人們預(yù)期WASM將會(huì)生長(zhǎng)出新的能力拓挥,那將超過JS能做的任何事情。例如袋励,讓JS演化出像線程這樣的根本特性 —— 一個(gè)肯定會(huì)對(duì)JS生態(tài)系統(tǒng)造成重大沖擊的改變 —— 作為一個(gè)WASM未來的擴(kuò)展更有希望侥啤,也會(huì)緩解改變JS的壓力。
事實(shí)上茬故,這張新的路線圖為許多語言服務(wù)于web運(yùn)行時(shí)開啟了新的道路盖灸。對(duì)于web平臺(tái)來說,這真是一個(gè)激動(dòng)人心的新路線磺芭!
它對(duì)JS意味著什么赁炎?JS將會(huì)變得無關(guān)緊要或者“死去”嗎?絕對(duì)不是钾腺。ASM.js在接下來的幾年中很可能看不到太多未來徙垫,但JS在數(shù)量上的絕對(duì)優(yōu)勢(shì)將它安全地錨定在web平臺(tái)中。
WASM的擁護(hù)者們說放棒,它的成功意味著JS的設(shè)計(jì)將會(huì)被保護(hù)起來姻报,遠(yuǎn)離那些最終會(huì)迫使它超過自己合理性的臨界點(diǎn)的壓力。人們估計(jì)WASM將會(huì)成為應(yīng)用程序中高性能部分的首選目標(biāo)語言间螟,這些部分曾用各種各樣不同的語言編寫過吴旋。
有趣的是,JavaScript是未來不太可能以WASM為目標(biāo)的語言之一厢破∪偕可能有一些未來的改變會(huì)切出JS的一部分,而使這一部分更適于以WASM作為目標(biāo)摩泪,但是這件事情看起來優(yōu)先級(jí)不高笆焰。
雖然JS很可能與WASM沒什么關(guān)聯(lián),但JS代碼和WASM代碼將能夠以最重要的方式進(jìn)行交互见坑,就像當(dāng)下的模塊互動(dòng)一樣自然仙辟。你可以想象同波,調(diào)用一個(gè)foo()
之類的JS函數(shù)而使它實(shí)際上調(diào)用一個(gè)同名WASM函數(shù),它具備遠(yuǎn)離你其余JS的制約而運(yùn)行的能力叠国。
至少是在可預(yù)見的未來未檩,當(dāng)下以JS編寫的東西可能將繼續(xù)總是由JS編寫。轉(zhuǎn)譯為JS的東西將可能最終至少考慮以WASM為目標(biāo)粟焊。對(duì)于那些需要極致性能冤狡,而且在抽象的層面上沒有余地的東西,最有可能的選擇是找一種合適的非JS語言編寫项棠,然后以WASM為目標(biāo)語言悲雳。
這個(gè)轉(zhuǎn)變很有可能將會(huì)很慢,會(huì)花上許多年成形香追。WASM在所有的主流瀏覽器上固定下來可能最快也要花幾年合瓢。同時(shí),WASM項(xiàng)目(https://github.com/WebAssembly)有一個(gè)早期填補(bǔ)透典,來為它的基本原則展示概念證明晴楔。
但隨著時(shí)間的推移,也隨著WASM學(xué)到新的非JS技巧峭咒,不難想象一些當(dāng)前是JS的東西被重構(gòu)為以WASM作為目標(biāo)的語言税弃。例如,框架中性能敏感的部分凑队,游戲引擎则果,和其他被深度使用的工具都很可能從這樣的轉(zhuǎn)變中獲益。在web應(yīng)用程序中使用這些工具的開發(fā)者們并不會(huì)在使用或整合上注意到太多不同漩氨,但確實(shí)會(huì)自動(dòng)地利用這些性能和能力西壮。
可以確定的是,隨著WASM變得越來越真實(shí)叫惊,它對(duì)JavaScript設(shè)計(jì)路線的影響就越來越多茸时。這可能是開發(fā)者們應(yīng)當(dāng)關(guān)注的最重要的“ES6以后”的話題。
復(fù)習(xí)
如果這個(gè)系列的其他書目實(shí)質(zhì)上提出了這個(gè)挑戰(zhàn)赋访,“你(可能)不懂JS(不像自己想象的那么懂)”可都,那么這本書就是在說,“你不再懂JS了”蚓耽。這本書講解了在ES6中加入到語言里的一大堆新東西渠牲。它是一個(gè)新語言特性的精彩集合,也是將永遠(yuǎn)改進(jìn)我們JS程序的范例步悠。
但JS不是到ES6就完了签杈!還早得很呢。已經(jīng)有好幾個(gè)“ES6之后”的特性處于開發(fā)的各個(gè)階段。在這一章中答姥,我們簡(jiǎn)要地看了一些最有可能很快會(huì)被固定在JS中的候選特性铣除。
async function
是建立在 generators + promises 模式(見第四章)上的強(qiáng)大語法糖。Object.observe(..)
為監(jiān)聽對(duì)象變化事件增加了直接原生的支持鹦付,它對(duì)實(shí)現(xiàn)數(shù)據(jù)綁定至關(guān)重要尚粘。**
指數(shù)作符,針對(duì)對(duì)象屬性的...
敲长,以及Array#includes(..)
都是對(duì)現(xiàn)存機(jī)制的簡(jiǎn)單而有用的改進(jìn)郎嫁。最后,SIMD將高性能JS的演化帶入一個(gè)新紀(jì)元祈噪。
聽起來很俗套泽铛,但JS的未來是非常光明的!這個(gè)系列辑鲤,以及這本書的挑戰(zhàn)盔腔,現(xiàn)在是各位讀者的職責(zé)了。你還在等什么月褥?是時(shí)候開始學(xué)習(xí)和探索了弛随!