你不懂JS:ES6與未來 第八章:ES6以后

官方中文版原文鏈接

感謝社區(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”。你可以在同一段代碼中使用yieldawait兩者彬檀,甚至是在同一個(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)的cd屬性重新收集到一個(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ū)分-00(參見本系列的 類型與文法)术浪。如果你在自己的程序中不關(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í)和探索了弛随!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市吓坚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌灯荧,老刑警劉巖礁击,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異逗载,居然都是意外死亡哆窿,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門厉斟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挚躯,“玉大人,你說我怎么就攤上這事擦秽÷肜螅” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵感挥,是天一觀的道長(zhǎng)缩搅。 經(jīng)常有香客問我,道長(zhǎng)触幼,這世上最難降的妖魔是什么硼瓣? 我笑而不...
    開封第一講書人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮置谦,結(jié)果婚禮上堂鲤,老公的妹妹穿的比我還像新娘亿傅。我一直安慰自己,他們只是感情好瘟栖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開白布葵擎。 她就那樣靜靜地躺著,像睡著了一般慢宗。 火紅的嫁衣襯著肌膚如雪坪蚁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,198評(píng)論 1 299
  • 那天镜沽,我揣著相機(jī)與錄音敏晤,去河邊找鬼。 笑死缅茉,一個(gè)胖子當(dāng)著我的面吹牛嘴脾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蔬墩,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼译打,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了拇颅?” 一聲冷哼從身側(cè)響起奏司,我...
    開封第一講書人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎樟插,沒想到半個(gè)月后韵洋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡黄锤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年搪缨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鸵熟。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡副编,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出流强,到底是詐尸還是另有隱情痹届,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布打月,位于F島的核電站短纵,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏僵控。R本人自食惡果不足惜香到,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧悠就,春花似錦千绪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至炸茧,卻和暖如春瑞妇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背梭冠。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來泰國打工辕狰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人控漠。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓蔓倍,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親盐捷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子偶翅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容