Psaní modulárního JavaScriptu pomocí AMD, CommonJS a ES Harmony

Tweet

Modularita Důležitost oddělení aplikace

Když říkáme, že je aplikace modulární, obvykle tím myslíme, že se skládá ze sady vysoce oddělených, samostatných částí funkcí uložených v modulech. Jak pravděpodobně víte, volné propojení usnadňuje údržbu aplikací tím, že odstraňuje závislosti, kde je to možné. Když je to implementováno efektivně, je poměrně snadné zjistit, jak mohou změny jedné části systému ovlivnit jinou.

Na rozdíl od některých tradičnějších programovacích jazyků však současná iterace jazyka JavaScript (ECMA-262) neposkytuje vývojářům prostředky pro čistý a organizovaný import takových modulů kódu. Je to jeden ze zádrhelů specifikací, které nevyžadovaly velké přemýšlení až do posledních let, kdy se ukázala potřeba organizovanějších aplikací v jazyce JavaScript.

Místo toho jsou vývojáři v současnosti odkázáni na varianty modulových nebo objektových literálních vzorů. U mnoha z nich jsou modulové skripty navlečeny v DOM dohromady, přičemž jmenné prostory jsou popsány jediným globálním objektem, kde je stále možné, že ve vaší architektuře dojde ke kolizi názvů. Neexistuje také žádný čistý způsob, jak zvládnout správu závislostí bez určitého ručního úsilí nebo nástrojů třetích stran.

Ačkoli nativní řešení těchto problémů přijdou v ES Harmony, dobrou zprávou je, že psaní modulárního JavaScriptu nebylo nikdy jednodušší a můžete s ním začít už dnes.

V tomto článku se podíváme na tři formáty pro psaní modulárního JavaScriptu:

Předmluva Poznámka k načítání skriptů

Je těžké diskutovat o modulech AMD a CommonJS, aniž bychom se zmínili o slonovi v místnosti – načítání skriptů. V současné době je načítání skriptů prostředkem k dosažení cíle, přičemž tímto cílem je modulární JavaScript, který lze používat v dnešních aplikacích – k tomu je bohužel nutné použití kompatibilního zavaděče skriptů. Abyste z tohoto článku vytěžili co nejvíce, doporučuji získat základní znalosti o tom, jak fungují populární nástroje pro načítání skriptů, aby vysvětlení formátů modulů dávalo smysl v kontextu.

Existuje řada skvělých načítacích nástrojů pro zpracování načítání modulů ve formátech AMD a CJS, ale já osobně preferuji RequireJS a curl.js. Kompletní návody na tyto nástroje jsou mimo rozsah tohoto článku, ale mohu doporučit přečíst si příspěvek Johna Hanna o curl.js a dokumentaci API RequireJS od Jamese Burkeho, kde najdete více.

Z produkčního hlediska se při práci s takovými moduly doporučuje pro nasazení používat optimalizační nástroje (jako je optimalizátor RequireJS) pro spojování skriptů. Zajímavé je, že díky Almond AMD shim nemusí být RequireJS v nasazeném webu rolován a to, co byste mohli považovat za načítání skriptů, lze snadno přesunout mimo vývoj.

James Burke by pravděpodobně řekl, že možnost dynamicky načítat skripty po načtení stránky má stále své případy použití a RequireJS s tím může také pomoci. S těmito poznámkami na mysli začněme.

AMD Formát pro psaní modulárního JavaScriptu v prohlížeči

Celkovým cílem formátu AMD (Asynchronous Module Definition) je poskytnout řešení pro modulární JavaScript, které mohou vývojáři používat již dnes. Vznikl na základě reálných zkušeností s používáním XHR+eval v systému Dojo a zastánci tohoto formátu se chtěli vyhnout tomu, aby jakákoli budoucí řešení trpěla nedostatky těch minulých.

Samotný formát modulů AMD je návrhem pro definici modulů, kdy modul i závislosti lze načítat asynchronně. Má řadu výrazných výhod, včetně toho, že je asynchronní a ze své podstaty vysoce flexibilní, což odstraňuje těsnou vazbu, kterou lze běžně nalézt mezi kódem a identitou modulu. Mnoho vývojářů jej rádo používá a lze jej považovat za spolehlivý odrazový můstek k modulovému systému navrženému pro ES Harmony.

AMD začal jako návrh specifikace formátu modulu na seznamu CommonJS, ale protože se nepodařilo dosáhnout plného konsenzu, přesunul se další vývoj formátu do skupiny amdjs.

Dnes jej přijaly projekty včetně Dojo (1.7), MooTools (2.0), Firebug (1.8) a dokonce i jQuery (1.7). Ačkoli se termín CommonJS AMD formát občas objevuje ve volné přírodě, je lepší jej označovat pouze jako AMD nebo Async Module support, protože ne všichni účastníci seznamu CJS si jej přáli prosazovat.

Poznámka: Byly doby, kdy byl návrh označován jako Modules Transport/C, nicméně vzhledem k tomu, že specifikace nebyla zaměřena na transport existujících modulů CJS, ale spíše na definování modulů, bylo rozumnější zvolit pojmenování AMD.

Začínáme s moduly

Dvěma klíčovými koncepcemi, které je zde třeba si uvědomit, je myšlenka define metody pro usnadnění definice modulů a require metody pro zpracování načítání závislostí. define se používá k definici pojmenovaných nebo nepojmenovaných modulů na základě návrhu pomocí následující signatury:

Jak můžete poznat z inline komentářů, module_id je nepovinný argument, který je obvykle vyžadován pouze při použití jiných než AMD konkatenačních nástrojů (mohou nastat i jiné okrajové případy, kdy je užitečný). Pokud tento argument vynecháme, nazýváme modul anonymním.

Při práci s anonymními moduly je myšlenka identity modulu DRY, takže je triviální vyhnout se duplicitě názvů souborů a kódu. Protože je kód přenositelnější, lze jej snadno přesunout na jiná místa (nebo po souborovém systému), aniž by bylo nutné měnit samotný kód nebo měnit jeho ID. Znak module_id je ekvivalentní cestám ke složkám v jednoduchých balíčcích a v případě, že se v balíčcích nepoužívá. Vývojáři mohou také spustit stejný kód ve více prostředích pouhým použitím optimalizátoru AMD, který pracuje s prostředím CommonJS, například r.js.

Zpět k signatuře define: Argument dependencies představuje pole závislostí, které jsou vyžadovány definovaným modulem, a třetí argument („definiční funkce“) je funkce, která se spustí pro instanci modulu. Základní modul by mohl být definován následujícím způsobem:

Podle AMD: define()

require se naopak obvykle používá k načtení kódu v souboru JavaScript nejvyšší úrovně nebo v rámci modulu, pokud chcete dynamicky načíst závislosti. Příkladem jeho použití je:

Pochopení AMD: require()

Dynamicky načítané závislosti

Pochopení AMD: zásuvné moduly

Následující příklad definování zásuvného modulu kompatibilního s AMD:

Poznámka: I když css! je ve výše uvedeném příkladu zahrnuto načítání závislostí CSS, je důležité si uvědomit, že tento přístup má některá úskalí, například není možné plně zjistit, kdy je CSS plně načteno. V závislosti na tom, jak přistupujete k sestavení, může také dojít k tomu, že CSS bude zahrnuto jako závislost v optimalizovaném souboru, takže v takových případech používejte CSS jako načtenou závislost s opatrností.

Načítání modulů AMD pomocí require.js

Zálohování modulů AMD pomocí curl.js

Moduly s odloženými závislostmi

Proč je AMD lepší volbou pro psaní modulárního JavaScriptu?

  • Předkládá jasný návrh, jak přistupovat k definování flexibilních modulů.
  • Je podstatně čistší než současné řešení globálních jmenných prostorů a značek <script>, na které se mnozí z nás spoléhají. Existuje čistý způsob, jak deklarovat samostatné moduly a závislosti, které mohou mít.
  • Definice modulů jsou zapouzdřené, což nám pomáhá vyhnout se znečištění globálního jmenného prostoru.
  • Funguje lépe než některá alternativní řešení (např. CommonJS, kterému se budeme brzy věnovat). Nemá problémy s mezidoménovým, lokálním nebo laděním a není závislé na použití nástrojů na straně serveru. Většina zavaděčů AMD podporuje načítání modulů v prohlížeči bez procesu sestavování.
  • Poskytuje „transportní“ přístup pro zahrnutí více modulů do jednoho souboru. Jiné přístupy, jako například CommonJS, se zatím na transportním formátu nedohodly.
  • Je možné líně načítat skripty, pokud je to potřeba.

Moduly AMD pomocí Dojo

Definování modulů kompatibilních s AMD pomocí Dojo je poměrně jednoduché. Jak je uvedeno výše, definujte všechny závislosti modulu v poli jako první argument a poskytněte zpětné volání (factory), které modul spustí, jakmile budou závislosti načteny. např.g:

define(, function( Tooltip ){ //Our dijit tooltip is now available for local use new Tooltip(...);});

Všimněte si anonymní povahy modulu, který nyní může být konzumován jak asynchronním zavaděčem Dojo, tak RequireJS nebo standardním zavaděčem modulů dojo.require(), který jste možná zvyklí používat.

Pro ty, kteří se zajímají o odkazování na moduly, je zde několik zajímavých zádrhelů, které je užitečné znát. Ačkoli AMD doporučovaný způsob odkazování na moduly je deklaruje v seznamu závislostí se sadou odpovídajících argumentů, není tento způsob podporován systémem sestavení Dojo 1.6 – funguje skutečně pouze pro zavaděče kompatibilní s AMD. např.g:

define(, function( cookie, Tooltip ){ var cookieValue = cookie("cookieName"); new Tree(...); });

Tento způsob má oproti vnořenému jmennému prostoru mnoho výhod, protože moduly již nemusí pokaždé přímo odkazovat na kompletní jmenný prostor – v závislostech vyžadujeme pouze cestu ‚dojo/cookie‘, na kterou se lze po přiřazení aliasu argumentu odkazovat pomocí této proměnné. Tím odpadá nutnost opakovaného vypisování ‚dojo.‘ ve vašich aplikacích.

Poznámka: Ačkoli Dojo 1.6 oficiálně nepodporuje uživatelské moduly AMD (ani asynchronní načítání), je možné toto zprovoznit v Dojo pomocí řady různých načítacích skriptů. V současné době byly všechny moduly jádra Dojo a Dijit převedeny na syntaxi AMD a vylepšená celková podpora AMD pravděpodobně přistane mezi verzemi 1.7 a 2.0.

Závěrečný háček, který je třeba si uvědomit, je, že pokud chcete nadále používat systém sestavení Dojo nebo chcete migrovat starší moduly na tento novější styl AMD, následující slovutnější verze umožňuje snadnější migraci. Všimněte si, že dojo a dijit a odkazovány také jako závislosti:

AMD Module Design Patterns (Dojo)

Pokud jste sledovali některý z mých předchozích příspěvků o výhodách návrhových vzorů, víte, že mohou být velmi účinné při zlepšování toho, jak přistupujeme ke strukturování řešení běžných vývojových problémů. John Hann nedávno přednesl vynikající prezentaci o návrhových vzorech modulů AMD zahrnující Singleton, Decorator, Mediator a další. Pokud budete mít příležitost, vřele doporučuji prohlédnout si jeho slajdy.

Několik ukázek těchto vzorů najdete níže:

Vzor Decorator:

Vzor adaptér

Moduly AMD s knihovnou jQuery

Základy

Na rozdíl od knihovny Dojo se knihovna jQuery skutečně dodává pouze s jedním souborem, avšak vzhledem k tomu, že je založena na zásuvných modulech, můžeme si níže ukázat, jak jednoduché je definovat modul AMD, který ji využívá.

V tomto příkladu však něco chybí, a to koncept registrace.

Registrace jQuery jako asynchronního modulu

Jednou z klíčových funkcí, které přistály v jQuery 1.7, byla podpora registrace jQuery jako asynchronního modulu. Existuje řada kompatibilních zavaděčů skriptů (včetně RequireJS a curl), které jsou schopny načítat moduly pomocí asynchronního formátu modulu, a to znamená, že je potřeba méně zásahů, aby vše fungovalo.

V důsledku popularity jQuery musí zavaděče AMD brát v úvahu více verzí knihovny načítaných do stejné stránky, protože v ideálním případě nechcete, aby se načítalo několik různých verzí současně. Nahrávače mají možnost buď tento problém výslovně zohlednit, nebo instruovat své uživatele o známých problémech se skripty třetích stran a jejich knihovnami.

Přídavek 1.7 přináší to, že pomáhá vyhnout se problémům s jiným kódem třetích stran na stránce, který by omylem načetl na stránce verzi jQuery, kterou vlastník nečekal. Nechcete přece, aby ostatní instance zahlcovaly vaši vlastní, a proto to může být přínosné.

Funguje to tak, že použitý načítací skript indikuje, že podporuje více verzí jQuery, tím, že uvede, že vlastnost define.amd.jQuery je rovna true. Pro ty, které zajímají konkrétnější podrobnosti implementace, registrujeme jQuery jako pojmenovaný modul, protože existuje riziko, že může být spojen s jinými soubory, které mohou používat metodu AMD define(), ale nepoužívají správný spojovací skript, který rozumí anonymním definicím modulů AMD.

Pojmenovaný AMD poskytuje pojistku, že je robustní a bezpečný pro většinu případů použití.

Modernější zásuvné moduly jQuery

Nedávno jsem zde probíral některé nápady a příklady, jak by se zásuvné moduly jQuery mohly psát pomocí vzorů UMD (Universal Module Definition). Vzory UMD definují moduly, které mohou pracovat jak na klientovi, tak na serveru a také se všemi populárními zavaděči skriptů, které jsou v současné době k dispozici. Přestože se stále jedná o novou oblast, kde se řada konceptů teprve dokončuje, neváhejte se podívat na ukázky kódu v názvu sekce AMD && CommonJS níže a dejte mi vědět, pokud máte pocit, že bychom mohli něco vylepšit.

Jaké rámce pro načítání skriptů & podporují AMD?

In-browser:
Server-side:
  • RequireJS http://requirejs.org
  • PINF http://github.com/pinf/loader-js

AMD Závěry

Výše uvedené jsou velmi triviální příklady toho, jak užitečné mohou moduly AMD skutečně být, ale snad poskytují základ pro pochopení jejich fungování.

Možná vás bude zajímat, že mnoho viditelných velkých aplikací a společností v současnosti používá moduly AMD jako součást své architektury. Patří mezi ně například IBM a BBC iPlayer, což jen podtrhuje, jak vážně o tomto formátu uvažují vývojáři na podnikové úrovni.

Pro více důvodů, proč se mnoho vývojářů rozhoduje pro používání modulů AMD ve svých aplikacích, vás může zajímat tento příspěvek Jamese Burka.

CommonJS Formát modulů optimalizovaný pro server

CommonJS jsou dobrovolnická pracovní skupina, jejímž cílem je navrhovat, vytvářet prototypy a standardizovat rozhraní API jazyka JavaScript. Dosud se pokusili ratifikovat standardy pro moduly i balíčky. Návrh modulů CommonJS specifikuje jednoduché API pro deklarování modulů na straně serveru a na rozdíl od AMD se pokouší pokrýt širší sadu problémů, jako je io, souborový systém, sliby a další.

Začínáme

Modul CJS je z hlediska struktury opakovaně použitelný kus JavaScriptu, který exportuje specifické objekty zpřístupněné jakémukoli závislému kódu – kolem takových modulů obvykle neexistují žádné obaly funkcí (takže se zde například nesetkáte s použitím define).

Na vysoké úrovni obsahují v zásadě dvě základní části: volnou proměnnou exports, která obsahuje objekty, jež chce modul zpřístupnit jiným modulům, a funkci require, kterou mohou moduly používat k importu exportů jiných modulů.

Pochopení CJS: require() a exporty

Základní konzumace exportů

AMD-ekvivalent prvního příkladu CJS

Konzumace více závislostí

app.js
bar.js
exports.name = 'bar';
foo.js
require('./bar');exports.helloWorld = function(){ return 'Hello World!!''}

Jaké načítací rámce & podporují CJS?

V prohlížeči:
  • curl.js http://github.com/unscriptable/curl
  • SproutCore 1.1 http://sproutcore.com
  • PINF http://github.com/pinf/loader-js
  • (a další)
Na straně serveru:

Je CJS vhodný pro prohlížeč?

Někteří vývojáři se domnívají, že CommonJS je vhodnější pro vývoj na straně serveru, což je jeden z důvodů, proč v současné době panují neshody o tom, který formát by měl být a bude používán jako de facto standard v době před Harmony a v budoucnu. Některé z argumentů proti CJS zahrnují poznámku, že mnoho API CommonJS řeší serverově orientované funkce, které by na úrovni prohlížeče v JavaScriptu jednoduše nebylo možné implementovat – například io, system a js by mohly být z povahy své funkčnosti považovány za neimplementovatelné.

Podle toho je užitečné vědět, jak strukturovat moduly CJS bez ohledu na to, abychom mohli lépe ocenit, jak se hodí při definování modulů, které se mohou používat všude. Mezi moduly, které mají uplatnění jak na klientovi, tak na serveru, patří validační, konverzní a šablonovací enginy. Někteří vývojáři přistupují k výběru formátu tak, že se rozhodnou pro CJS, pokud lze modul použít v prostředí na straně serveru, a pro AMD, pokud tomu tak není.

Jelikož moduly AMD mohou používat zásuvné moduly a mohou definovat podrobnější věci, jako jsou konstruktory a funkce, dává to smysl. Moduly CJS jsou schopny definovat pouze objekty, s nimiž může být práce zdlouhavá, pokud se z nich snažíte získat konstruktory.

Ačkoli to přesahuje rámec tohoto článku, možná jste si také všimli, že při diskusi o AMD a CJS byly zmíněny různé typy metod ‚require‘.

Obava z podobného pojmenování je samozřejmě matoucí a komunita je v současné době rozdělena v názoru na výhody globální funkce require. John Hann zde navrhuje, že namísto názvu „require“, který by pravděpodobně nedosáhl cíle informovat uživatele o rozdílu mezi globálním a vnitřním require, by možná bylo rozumnější přejmenovat metodu globálního zavaděče na něco jiného (např. na název knihovny). Z tohoto důvodu se u zavaděče, jako je curl.js, používá curl() na rozdíl od require.

AMD && CommonJS Konkurenční, ale stejně platné standardy

Ačkoli tento článek kladl větší důraz na používání AMD než CJS, ve skutečnosti jsou oba formáty platné a mají své využití.

AMD uplatňuje přístup k vývoji zaměřený na prohlížeč, volí asynchronní chování a zjednodušenou zpětnou kompatibilitu, ale nemá žádný koncept souborového vstupu/výstupu. Podporuje objekty, funkce, konstruktory, řetězce, JSON a mnoho dalších typů modulů, které běží nativně v prohlížeči. Je neuvěřitelně flexibilní.

CommonJS naproti tomu zaujímá přístup server-first, předpokládá synchronní chování, žádné globální zavazadlo, jak by to nazval John Hann, a snaží se počítat s budoucností (na serveru). Máme tím na mysli, že díky tomu, že CJS podporuje nezabalené moduly, může se cítit o něco blíže specifikacím ES.next/Harmony, což vás osvobodí od define()obalu, který prosazuje AMD. Moduly CJS však podporují pouze objekty jako moduly.

Ačkoli vás představa dalšího formátu modulů může odrazovat, možná vás zaujmou některé ukázky práce na hybridních modulech AMD/CJS a univerzálních modulech AMD/CJS.

Základní hybridní formát AMD (John Hann)

Definice univerzálních modulů AMD/CommonJS (Varianta 2, UMDjs)

Rozšiřitelné zásuvné moduly UMD s (Varianta podle mě a Thomase Davise).

core.js
myExtension.js
;(function ( name, definition ) { var theModule = definition(), hasDefine = typeof define === 'function', hasExports = typeof module !== 'undefined' && module.exports; if ( hasDefine ) { // AMD Module define(theModule); } else if ( hasExports ) { // Node.js Module module.exports = theModule; } else { // Assign to common namespaces or simply the global object (window) // account for for flat-file/global module extensions var obj = null; var namespaces = name.split("."); var scope = (this.jQuery || this.ender || this.$ || this); for (var i = 0; i 
app.js
$(function(){ // the plugin 'core' is exposed under a core namespace in // this example which we first cache var core = $.core; // use then use some of the built-in core functionality to // highlight all divs in the page yellow core.highlightAll(); // access the plugins (extensions) loaded into the 'plugin' // namespace of our core module: // Set the first div in the page to have a green background. core.plugin.setGreen("div:first"); // Here we're making use of the core's 'highlight' method // under the hood from a plugin loaded in after it // Set the last div to the 'errorColor' property defined in // our core module/plugin. If you review the code further down // you'll see how easy it is to consume properties and methods // between the core and other plugins core.plugin.setRed('div:last');});

ES Harmony Modules Of The Future

TC39, normalizační orgán pověřený definováním syntaxe a sémantiky jazyka ECMAScript a jeho budoucích iterací, je složen z řady velmi inteligentních vývojářů. Někteří z těchto vývojářů (například Alex Russell) v posledních několika letech pozorně sledují vývoj používání jazyka JavaScript pro rozsáhlý vývoj a jsou si velmi dobře vědomi potřeby lepších vlastností jazyka pro psaní modulárnějšího JS.

Z tohoto důvodu je v současné době navrhována řada zajímavých doplňků jazyka, včetně flexibilních modulů, které mohou pracovat na klientovi i serveru, načítání modulů a dalších. V této části vám ukážu několik ukázek kódu syntaxe pro moduly v ES.next, abyste mohli ochutnat, co se chystá.

Poznámka: Ačkoli je Harmony stále ve fázi návrhů, můžete si již vyzkoušet (částečné) funkce ES.next, které řeší nativní podporu psaní modulárního JavaScriptu díky kompilátoru Traceur od společnosti Google. Chcete-li Traceur zprovoznit během necelé minuty, přečtěte si tuto úvodní příručku. Existuje o něm také prezentace na konferenci JSConf, která stojí za zhlédnutí, pokud máte zájem dozvědět se o projektu více.

Moduly s importy a exporty

Pokud jste si přečetli části o modulech AMD a CJS, možná znáte koncept závislostí modulů (importů) a exportů modulů (neboli veřejných API/proměnných, které umožňujeme jiným modulům konzumovat). V ES.next byly tyto koncepty navrženy poněkud stručněji, přičemž závislosti jsou specifikovány pomocí klíčového slova import. export se nijak výrazně neliší od toho, co bychom mohli očekávat, a myslím, že mnoho vývojářů se podívá na níže uvedený kód a okamžitě ho "pochopí".

  • deklarace importu vážou exporty modulu jako lokální proměnné a mohou být přejmenovány, aby se předešlo kolizím/konfliktům názvů.
  • deklarace exportu deklarují, že lokální vazba modulu je externě viditelná, takže ostatní moduly mohou exporty číst, ale nemohou je měnit. Zajímavé je, že moduly mohou exportovat podřízené moduly, nemohou však exportovat moduly, které byly definovány jinde. Můžete také přejmenovat exporty tak, aby se jejich externí název lišil od jejich lokálního názvu.

Moduly načítané ze vzdálených zdrojů

Návrhy modulů také vyhovují modulům, které jsou založeny vzdáleně (např. obal API třetí strany), což zjednodušuje načítání modulů z externích umístění. Zde je příklad, kdy vytáhneme modul, který jsme definovali výše, a využijeme ho:

Module Loader API

Navržený modul loader popisuje dynamické API pro načítání modulů ve vysoce kontrolovaném kontextu. Mezi signatury podporované v zavaděči patří load( url, moduleInstance, error) pro načítání modulů, createModule( object, globalModuleReferences) a další. Zde je další příklad, kdy dynamicky načítáme v modulu, který jsme původně definovali. Všimněte si, že na rozdíl od minulého příkladu, kdy jsme modul natáhli ze vzdáleného zdroje, je rozhraní API zavaděče modulů vhodnější pro dynamické kontexty.

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

Moduly podobné CommonJS pro server

Pro vývojáře, kteří se orientují na server, není systém modulů navržený pro ES.next omezen pouze na prohlížení modulů v prohlížeči. Níže si pro příklad můžete prohlédnout modul podobný CJS navržený pro použití na serveru:

// io/File.jsexport function open(path) { ... };export function close(hnd) { ... };
module lexer from 'compiler/LexicalHandler';module stdlib from '@std'; //... scan(cmdline) ...

Třídy s konstruktory, gettery & settery

Pojmem třída se puristé vždy zabývali sporně a dosud jsme si vystačili buď s návratem k prototypové povaze JavaScriptu, nebo pomocí frameworků či abstrakcí, které nabízejí možnost používat definice tříd v podobě, která desugarizuje stejné prototypové chování.

V Harmony přicházejí třídy jako součást jazyka spolu s konstruktory a (konečně) určitým smyslem pro skutečné soukromí. V následujících příkladech jsem uvedl několik inline komentářů, které vám pomohou pochopit, jak jsou třídy strukturovány, ale můžete si také všimnout, že zde chybí slovo „funkce“. Nejedná se o chybu překlepu: TC39 se vědomě snaží omezit zneužívání klíčového slova function pro všechno a doufá, že to pomůže zjednodušit způsob, jakým píšeme kód.

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 

ES Harmony Conclusions

As you can see, ES.next is coming with some exciting new additions. Although Traceur can be used to an extent to try our such features in the present, remember that it may not be the best idea to plan out your system to use Harmony (just yet). There are risks here such as specifications changing and a potential failure at the cross-browser level (IE9 for example will take a while to die) so your best bets until we have both spec finalization and coverage are AMD (for in-browser modules) and CJS (for those on the server).

Conclusions And Further Reading A Review

In this article we've reviewed several of the options available for writing modular JavaScript using modern module formats. These formats have a number of advantages over using the (classical) module pattern alone including: avoiding a need for developers to create global variables for each module they create, better support for static and dynamic dependency management, improved compatibility with script loaders, better (optional) compatibility for modules on the server and more.

In short, I recommend trying out what's been suggested today as these formats offer a lot of power and flexibility that can help when building applications based on many reusable blocks of functionality.

And that's it for now. If you have further questions about any of the topics covered today, feel free to hit me up on twitter and I'll do my best to help!

Copyright Addy Osmani, 2012. All Rights Reserved.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.