鍍金池/ 教程/ HTML/ ES Harmony
中介者模式
MVVM
亨元模式
設(shè)計(jì)模式分類概覽表
ES Harmony
組合模式
CommonJS
jQuery 插件的設(shè)計(jì)模式
外觀模式
觀察者模式
建造者模式
構(gòu)造器模式
外觀模式
簡介
AMD
原型模式
設(shè)計(jì)模式的分類
觀察者模式
命名空間模式
代理模式
編寫設(shè)計(jì)模式
適配器模式
反模式
什么是設(shè)計(jì)模式
模塊化模式
MVC
Mixin 模式
裝飾模式
設(shè)計(jì)模式的結(jié)構(gòu)
單例模式
迭代器模式
命令模式
工廠模式
MVP
暴露模塊模式
惰性初始模式

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)有大量激動(dòng)人心的,包括在客戶端和服務(wù)器上都能起作用的彈性模塊,一個(gè)模塊加載器以及更多的對語言的改進(jìn)提議。在這一節(jié)中,我們將使用ES.next中為模塊提供的語法來探討代碼示例,以使我們能夠嘗一嘗它是什么味道。

注意:盡管Harmony仍然處于建設(shè)性階段,我們也已經(jīng)可以嘗試ES.netx的(部分)特性了,而這得感謝Google的Traceur編譯器為模塊化的Javascript提供的原生支持。為了在短時(shí)間內(nèi)使Traceur啟動(dòng)和運(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)境中加載模塊的動(dòng)態(tài)API。加載器上支持的簽名包含load(url, moduleInstance, error)用于加載模塊,createModule(object, globalModuleReferences)以及其他的操作。

這里是另外一個(gè)我們最初定義的在模塊中進(jìn)行動(dòng)態(tài)加載的示例。注意,并不像我們最近的一個(gè)從遠(yuǎn)程來源拉入一個(gè)模塊的示例,模塊加載器API更加適合于動(dòng)態(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ā)工作變得輕松的令人激動(dòng)附加功能,還為我們處理了諸如依賴管理的問題。

目前,我們在今天的瀏覽器中使用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)和動(dòng)態(tài)的依賴管理,提高腳本裝載機(jī)的兼容性,在服務(wù)器上以及更多的平臺上,能夠獲得更好的兼容性。

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