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展示就值得看一看。
已經(jīng)通讀過AMD和CommonJS章節(jié)的話,你也許熟悉模塊依賴(導(dǎo)入)和模塊導(dǎo)出(或者說是我們允許其它模塊使用的公共API/變量)這兩個(gè)概念。在ES.next中,這些概念已經(jīng)使用一種同我們預(yù)期沒太大不同,而開發(fā)者將可以在代碼示例中往下看到并且能瞬間抓住的用一個(gè)export關(guā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)程來源的模塊(例如,一個(gè)第三方庫),這簡化了從外部位置載入模塊的操作。這里有一個(gè)在模塊中抽取并使用它的示例:
module cakeFactory from "http://addyosmani.com/factory/cakes.js";
cakeFactory.oven.makeCupcake( "sprinkles" );
cakeFactory.oven.makeMuffin( "large" );
被提出來的模塊加載器描述了一個(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ù)器環(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]) ...
類的概念一直都是帶有純粹主義色彩的有爭議的問題,而我們目前相對已經(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;
}
}
正如我們已經(jīng)看到的,Harmony帶來了一些可以使模塊化應(yīng)用程序的開發(fā)工作變得輕松的令人激動附加功能,還為我們處理了諸如依賴管理的問題。
目前,我們在今天的瀏覽器中使用Harmony語法的最好選擇是通過一個(gè)轉(zhuǎn)換編譯器,比如Google的Traceur或者Esprima。也有諸如Require HM的項(xiàng)目允許使用帶有AMD的Harmony模塊。在規(guī)范定稿以前,我們最好把賭注壓在AMD(在瀏覽器的模塊)和CommonJS(對于那些在服務(wù)器上的模塊)。
在這一節(jié)中,我們回顧了一些 使用現(xiàn)代化的模塊化形式編寫模塊化JavaScript的選擇。
這些形式在利用 模塊模式上有眾多的優(yōu)勢,包括:避免管理全局變量的必要,更好地支持靜態(tài)和動態(tài)的依賴管理,提高腳本裝載機(jī)的兼容性,在服務(wù)器上以及更多的平臺上,能夠獲得更好的兼容性。
總之,我建議去嘗試一下本章所提供的建議,因?yàn)檫@些格式提供了很大的強(qiáng)有力的靈活性,對更好地組織我們的應(yīng)用程序有著明顯的幫助。
更多建議: