# ES Harmony
## 未來的模塊
[TC39](http://www.ecma-international.org/memento/TC39.htm),負責討論ECMAScript語法和語義定義問題和其未來迭代的標準機構,它是由許多的非常聰明的開發者組成的。這些開發者中的一些人(比如Alex Russell)對Javascript在大規模開發中的用例場景在過去幾年一直保持者密切的關注,并且敏銳的意識到了人們對于能夠使用其編寫更加模塊化JS的優良的語言特性的需求。 出于這個原因,目前已經有大量激動人心的,包括在客戶端和服務器上都能起作用的彈性模塊,一個模塊加載器以及更多的對語言的改進提議。在這一節中,我們將使用ES.next中為模塊提供的語法來探討代碼示例,以使我們能夠嘗一嘗它是什么味道。
> 注意:盡管Harmony仍然處于建設性階段,我們也已經可以嘗試ES.netx的(部分)特性了,而這得感謝Google的Traceur編譯器為模塊化的Javascript提供的原生支持。為了在短時間內使Traceur啟動和運作起來,讀一讀這份初學指導吧。如果對更深入的了解這個項目感興趣的話,一個關于它JSConf展示就值得看一看。
## 使用導入和導出的模塊
已經通讀過AMD和CommonJS章節的話,你也許熟悉模塊依賴(導入)和模塊導出(或者說是我們允許其它模塊使用的公共API/變量)這兩個概念。在ES.next中,這些概念已經使用一種同我們預期沒太大不同,而開發者將可以在代碼示例中往下看到并且能瞬間抓住的用一個export關鍵字指定依賴的稍微更簡潔的方式,被提供了出來。
* import聲明綁定了一個以本地變量身份導出的模塊,而且可能被重命名以避免名稱重復或沖突。
* export聲明聲明了模塊本地綁定的外部可見性,那樣其他模塊就可能讀取到導出但不能修改它們。有趣的是,模塊可能導出子模塊但不能夠導出已經在另外一個地方定義的模塊。我們也可以對導出進行重命名以便它們的外部名稱同本地名稱有所不同。
~~~
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 );
}
}
}
~~~
## 從遠程來源加載的模塊
模塊的提案也支持基于遠程來源的模塊(例如,一個第三方庫),這簡化了從外部位置載入模塊的操作。這里有一個在模塊中抽取并使用它的示例:
~~~
module cakeFactory from "http://addyosmani.com/factory/cakes.js";
cakeFactory.oven.makeCupcake( "sprinkles" );
cakeFactory.oven.makeMuffin( "large" );
~~~
## 模塊加載API
被提出來的模塊加載器描述了一個用于在一個被高度控制的環境中加載模塊的動態API。加載器上支持的簽名包含load(url, moduleInstance, error)用于加載模塊,createModule(object, globalModuleReferences)以及其他的操作。
這里是另外一個我們最初定義的在模塊中進行動態加載的示例。注意,并不像我們最近的一個從遠程來源拉入一個模塊的示例,模塊加載器API更加適合于動態環境。
~~~
Loader.load( "http://addyosmani.com/factory/cakes.js" ,
function( cakeFactory ){
cakeFactory.oven.makeCupcake( "chocolate" );
});
~~~
## 針對服務器的CommonJS類似模塊
對于那些對服務器環境更加感興趣的開發者,ES.next提供的模塊系統并不僅僅限制只在瀏覽器中尋找模塊。例如在下面,我們能夠看到一個CommonJS類似的模塊被提供給在服務器上使用。
~~~
// 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]) ...
~~~
## 帶有構造器,Get和Set方法的類
類的概念一直都是帶有純粹主義色彩的有爭議的問題,而我們目前相對已經回落到關于Javascript原型性質的問題上來,或者通過使用提供在一個表單中使用類定義能力的框架或者抽象,其具有相同原型行為的語法糖。
在Harmony中,為這種語言類已經同構造器和一些(最終)具有某種意義的真正隱晦的東西一起,被提了出來。在下面的示例中,其中的注釋提供了用于幫助解釋類是如何被構造的問題。
通過閱讀,人們也許也會意識到這里“function“世界的缺失。這并不是一個筆誤:TC39已經做出有目的的嘗試,降低我們在任何事物上對function關鍵字的濫用,而這其實是希望能夠簡化我們編寫代碼的工作。
~~~
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 總結
正如我們已經看到的,Harmony帶來了一些可以使模塊化應用程序的開發工作變得輕松的令人激動附加功能,還為我們處理了諸如依賴管理的問題。
目前,我們在今天的瀏覽器中使用Harmony語法的最好選擇是通過一個轉換編譯器,比如Google的Traceur或者Esprima。也有諸如Require HM的項目允許使用帶有AMD的Harmony模塊。在規范定稿以前,我們最好把賭注壓在AMD(在瀏覽器的模塊)和CommonJS(對于那些在服務器上的模塊)。
## 相關閱讀
* [初步了解即將到來的JavaScript模塊](http://www.2ality.com/2011/03/first-look-at-upcoming-javascript.html)
* [David Herman關于JavaScript/ES.Next的探討 (視頻)](http://blog.mozilla.com/dherman/2011/02/23/my-js-meetup-talk/)
* [關于 ES Harmony 模塊的建議](http://wiki.ecmascript.org/doku.php?id=harmony:modules)
* [ES Harmony 模塊語義/結構原理](http://wiki.ecmascript.org/doku.php?id=harmony:modules_rationale)
* [關于 ES Harmony 類的建議](http://wiki.ecmascript.org/doku.php?id=harmony:classes)
## 結論
在這一節中,我們回顧了一些 使用現代化的模塊化形式編寫模塊化JavaScript的選擇。
這些形式在利用 模塊模式上有眾多的優勢,包括:避免管理全局變量的必要,更好地支持靜態和動態的依賴管理,提高腳本裝載機的兼容性,在服務器上以及更多的平臺上,能夠獲得更好的兼容性。
總之,我建議去嘗試一下本章所提供的建議,因為這些格式提供了很大的強有力的靈活性,對更好地組織我們的應用程序有著明顯的幫助。
- 前言
- 簡介
- 什么是設計模式?
- 設計模式的結構
- 編寫設計模式
- 反模式
- 設計模式的分類
- 設計模式分類概覽表
- JavaScript 設計模式
- 構造器模式
- 模塊化模式
- 暴露模塊模式
- 單例模式
- 觀察者模式
- 中介者模式
- 原型模式
- 命令模式
- 外觀模式
- 工廠模式
- Mixin 模式
- 裝飾模式
- 亨元(Flyweight)模式
- JavaScript MV* 模式
- MVC 模式
- MVP 模式
- MVVM 模式
- 最新的模塊化 JavaScript 設計模式
- AMD
- CommonJS
- ES Harmony
- JQuery 中的設計模式
- 組合模式
- 適配器模式
- 外觀模式
- 觀察者模式
- 迭代器模式
- 惰性初始模式
- 代理模式
- 建造者模式
- jQuery 插件的設計模式
- JavaScript 命名空間模式
- 總結
- 參考