ES Harmony 特性

2021-09-15 11:17 更新

ES Harmony

未來的模塊

TC39,負(fù)責(zé)討論ECMAScript語法和語義定義問題和其未來迭代的標(biāo)準(zhǔn)機(jī)構(gòu),它是由許多的非常聰明的開發(fā)者組成的。這些開發(fā)者中的一些人(比如Alex Russell)對Javascript在大規(guī)模開發(fā)中的用例場景在過去幾年一直保持者密切的關(guān)注,并且敏銳的意識到了人們對于能夠使用其編寫更加模塊化JS的優(yōu)良的語言特性的需求。 出于這個(gè)原因,目前已經(jīng)有大量激動人心的,包括在客戶端和服務(wù)器上都能起作用的彈性模塊,一個(gè)模塊加載器以及更多的對語言的改進(jìn)提議。在這一節(jié)中,我們將使用ES.next中為模塊提供的語法來探討代碼示例,以使我們能夠嘗一嘗它是什么味道。

注意:盡管Harmony仍然處于建設(shè)性階段,我們也已經(jīng)可以嘗試ES.next的(部分)特性了,而這得感謝Google的Traceur編譯器為模塊化的Javascript提供的原生支持。為了在短時(shí)間內(nèi)使Traceur啟動和運(yùn)作起來,讀一讀這份初學(xué)指導(dǎo)吧。如果對更深入的了解這個(gè)項(xiàng)目感興趣的話,一個(gè)關(guān)于它JSConf展示就值得看一看。

使用導(dǎo)入和導(dǎo)出的模塊

已經(jīng)通讀過AMD和CommonJS章節(jié)的話,你也許熟悉模塊依賴(導(dǎo)入)和模塊導(dǎo)出(或者說是我們允許其它模塊使用的公共API/變量)這兩個(gè)概念。在ES.next中,這些概念已經(jīng)使用一種同我們預(yù)期沒太大不同,而開發(fā)者將可以在代碼示例中往下看到并且能瞬間抓住的用一個(gè)export關(guān)鍵字指定依賴的稍微更簡潔的方式,被提供了出來。

  • import聲明綁定了一個(gè)以本地變量身份導(dǎo)出的模塊,而且可能被重命名以避免名稱重復(fù)或沖突。
  • export聲明聲明了模塊本地綁定的外部可見性,那樣其他模塊就可能讀取到導(dǎo)出但不能修改它們。有趣的是,模塊可能導(dǎo)出子模塊但不能夠?qū)С鲆呀?jīng)在另外一個(gè)地方定義的模塊。我們也可以對導(dǎo)出進(jìn)行重命名以便它們的外部名稱同本地名稱有所不同。
module staff{
    // specify (public) exports that can be consumed by
    // other modules
    export var baker = {
        bake: function( item ){
            console.log( "Woo! I just baked " + item );
        }
    }  
}

module skills{
    export var specialty = "baking";
    export var experience = "5 years";
}

module cakeFactory{

    // specify dependencies
    import baker from staff;

    // import everything with wildcards
    import * from skills;

    export var oven = {
        makeCupcake: function( toppings ){
            baker.bake( "cupcake", toppings );
        },
        makeMuffin: function( mSize ){
            baker.bake( "muffin", size );
        }
    }
}

從遠(yuǎn)程來源加載的模塊

模塊的提案也支持基于遠(yuǎn)程來源的模塊(例如,一個(gè)第三方庫),這簡化了從外部位置載入模塊的操作。這里有一個(gè)在模塊中抽取并使用它的示例:

module cakeFactory from "http://addyosmani.com/factory/cakes.js";
cakeFactory.oven.makeCupcake( "sprinkles" );
cakeFactory.oven.makeMuffin( "large" );

模塊加載API

被提出來的模塊加載器描述了一個(gè)用于在一個(gè)被高度控制的環(huán)境中加載模塊的動態(tài)API。加載器上支持的簽名包含load(url, moduleInstance, error)用于加載模塊,createModule(object, globalModuleReferences)以及其他的操作。

這里是另外一個(gè)我們最初定義的在模塊中進(jìn)行動態(tài)加載的示例。注意,并不像我們最近的一個(gè)從遠(yuǎn)程來源拉入一個(gè)模塊的示例,模塊加載器API更加適合于動態(tài)環(huán)境。

Loader.load( "http://addyosmani.com/factory/cakes.js" ,
    function( cakeFactory ){
        cakeFactory.oven.makeCupcake( "chocolate" );
    });

針對服務(wù)器的CommonJS類似模塊

對于那些對服務(wù)器環(huán)境更加感興趣的開發(fā)者,ES.next提供的模塊系統(tǒng)并不僅僅限制只在瀏覽器中尋找模塊。例如在下面,我們能夠看到一個(gè)CommonJS類似的模塊被提供給在服務(wù)器上使用。

// io/File.js
export function open( path ) { ... };
export function close( hnd ) { ... };
// compiler/LexicalHandler.js
module file from "io/File";

import { open, close } from file;
export function scan( in ) {
    try {
        var h = open( in ) ...
    }
    finally { close( h ) }
}
module lexer from "compiler/LexicalHandler";
module stdlib from "@std";

//... scan(cmdline[0]) ...

帶有構(gòu)造器,Get和Set方法的類

類的概念一直都是帶有純粹主義色彩的有爭議的問題,而我們目前相對已經(jīng)回落到關(guān)于Javascript原型性質(zhì)的問題上來,或者通過使用提供在一個(gè)表單中使用類定義能力的框架或者抽象,其具有相同原型行為的語法糖。

在Harmony中,為這種語言類已經(jīng)同構(gòu)造器和一些(最終)具有某種意義的真正隱晦的東西一起,被提了出來。在下面的示例中,其中的注釋提供了用于幫助解釋類是如何被構(gòu)造的問題。

通過閱讀,人們也許也會意識到這里“function“世界的缺失。這并不是一個(gè)筆誤:TC39已經(jīng)做出有目的的嘗試,降低我們在任何事物上對function關(guān)鍵字的濫用,而這其實(shí)是希望能夠簡化我們編寫代碼的工作。

class Cake{

    // We can define the body of a class" constructor
    // function by using the keyword "constructor" followed
    // by an argument list of public and private declarations.
    constructor( name, toppings, price, cakeSize ){
        public name = name;
        public cakeSize = cakeSize;
        public toppings = toppings;
        private price = price;

    }

    // As a part of ES.next's efforts to decrease the unnecessary
    // use of "function" for everything, you'll notice that it's
    // dropped for cases such as the following. Here an identifier
    // followed by an argument list and a body defines a new method

    addTopping( topping ){
        public( this ).toppings.push( topping );
    }

    // Getters can be defined by declaring get before
    // an identifier/method name and a curly body.
    get allToppings(){
        return public( this ).toppings;
    }

    get qualifiesForDiscount(){
        return private( this ).price > 5;
    }

    // Similar to getters, setters can be defined by using
    // the "set" keyword before an identifier
    set cakeSize( cSize ){
        if( cSize < 0 ){
            throw new Error( "Cake must be a valid size -
            either small, medium or large" );
        }
        public( this ).cakeSize = cSize;
    }

}

ES Harmony 總結(jié)

正如我們已經(jīng)看到的,Harmony帶來了一些可以使模塊化應(yīng)用程序的開發(fā)工作變得輕松的令人激動附加功能,還為我們處理了諸如依賴管理的問題。

目前,我們在今天的瀏覽器中使用Harmony語法的最好選擇是通過一個(gè)轉(zhuǎn)換編譯器,比如Google的Traceur或者Esprima。也有諸如Require HM的項(xiàng)目允許使用帶有AMD的Harmony模塊。在規(guī)范定稿以前,我們最好把賭注壓在AMD(在瀏覽器的模塊)和CommonJS(對于那些在服務(wù)器上的模塊)。

相關(guān)閱讀

結(jié)論

在這一節(jié)中,我們回顧了一些 使用現(xiàn)代化的模塊化形式編寫模塊化JavaScript的選擇。

這些形式在利用 模塊模式上有眾多的優(yōu)勢,包括:避免管理全局變量的必要,更好地支持靜態(tài)和動態(tài)的依賴管理,提高腳本裝載機(jī)的兼容性,在服務(wù)器上以及更多的平臺上,能夠獲得更好的兼容性。

總之,我建議去嘗試一下本章所提供的建議,因?yàn)檫@些格式提供了很大的強(qiáng)有力的靈活性,對更好地組織我們的應(yīng)用程序有著明顯的幫助。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號