Programiranje

Koda v JavaScript je pametna, modularna

Nekateri so še vedno presenečeni nad tem, da JavaScript velja za ugleden, odrasel programski jezik za resne aplikacije. Pravzaprav razvoj JavaScript-ov že leta lepo zori in najboljši primer so najboljše prakse modularnega razvoja.

Prednosti pisanja modularne kode so dobro dokumentirane: večja vzdrževalnost, izogibanje monolitnim datotekam in ločevanje kode v enote, ki jih je mogoče pravilno preizkusiti. Za tiste, ki bi se radi hitro ujeli, tukaj so običajne prakse sodobnih razvijalcev JavaScript za pisanje modularizirane kode.

Vzorec modula

Začnimo z osnovnim vzorcem oblikovanja, imenovanim modularni vzorec. Kot lahko sumite, nam to omogoča modularno pisanje kode, ki nam omogoča zaščito konteksta izvajanja danih modulov in globalno razkritje le tistega, kar želimo izpostaviti. Vzorec je videti nekako tako:

(funkcija () {

// 'zasebna' spremenljivka

var orderId = 123;

// izpostavljamo metode in spremenljivke tako, da jih pritrdimo

// na globalni objekt

window.orderModule = {

getOrderId: function () {

// vam ga prinese zaprtje

return orderId;

}

};

})()

Anonimnafunkcijo izraz, ki v tem primeru deluje kot tovarna, je napisan in poklican takoj. Za hitrost lahko spremenljivke izrecno prenesete nafunkcijo klic, ki dejansko ponovno poveže te spremenljivke na lokalni obseg. To boste včasih videli tudi kot obrambni manever v knjižnicah, ki podpirajo stare brskalnike, kjer so določene vrednosti (nprnedoločeno) so zapisljive lastnosti.

(funkcija (globalno, nedoločeno) {

// koda tukaj lahko hitro dostopa do globalnega predmeta,

// in 'undefined' bo zagotovo 'undefined'

// OPOMBA: V sodobnih brskalnikih 'undefined' ni zapisljiv,

// vendar je vredno to upoštevati

// pri pisanju kode za stare brskalnike.

}) (to)

To je le oblikovalski vzorec. S to tehniko vam za pisanje modularnega JavaScript ni treba vključiti dodatnih knjižnic. Pomanjkanje odvisnosti je v nekaterih nastavitvah velik plus (ali kritična naloga), zlasti če pišete knjižnico. Videli boste, da bo večina priljubljenih knjižnic uporabila ta vzorec za inkapsuliranje notranjih funkcij in spremenljivk, pri čemer bo izpostavila samo tisto, kar je potrebno.

Če pišete prijavo, pa ima ta pristop nekaj slabosti. Recimo, da ustvarite modul, ki nastavi nekaj metodokno.naročila. Če želite te metode uporabiti v drugih delih vaše aplikacije, se morate prepričati, da je modul vključen, preden jih pokličete. Nato v kodi, kamor kličetewindow.orders.getOrderId, napišete kodo in upate, da se je naložil drugi skript.

To se morda ne zdi konec sveta, vendar lahko pri zapletenih projektih hitro uide nadzoru - in upravljanje naročila za vključitev skriptov postane bolečina. Prav tako morajo biti vse vaše datoteke sinhrono naložene, sicer boste vanj povabili dirkalne pogoje, da boste zlomili kodo. Ko bi le obstajal način, kako izrecno razglasiti module, ki ste jih želeli uporabiti za dani bit kode ....

AMD (definicija asinhronega modula)

AMD se je rodil iz potrebe po določanju eksplicitnih odvisnosti, hkrati pa se je izognil sinhronemu nalaganju vseh skriptov. V brskalniku je enostaven za uporabo, vendar ni domač, zato morate vključiti knjižnico, ki izvaja nalaganje skriptov, na primer RequireJS ali curl.js. Tukaj je videti, kako definirati modul z uporabo AMD:

// libs / order-module.js

define (function () {

// 'zasebna' spremenljivka

var orderId = 123;

// razkrijemo metode in spremenljivke tako, da jih vrnemo

vrni {

getOrderId: function () {

return orderId;

}

});

Videti je podobno kot prej, le da namesto da bi takoj poklicali svojo tovarniško funkcijo, ga posredujemo kot argumentopredeliti. Prava čarovnija se začne dogajati, ko želite kasneje uporabiti modul:

define (['libs / order-module'], funkcija (orderModule) {

orderModule.getOrderId (); // oceni na 123

});

Prvi argumentopredeliti je zdaj vrsta odvisnosti, ki je lahko poljubno dolga, tovarniška funkcija pa navaja formalne parametre za tiste odvisnosti, ki ji bodo pritrjene. Zdaj lahko nekatere odvisnosti, ki jih potrebujete, imajo lastne odvisnosti, toda z AMD vam ni treba vedeti, da:

// src / utils.js

define (['libs / podčrtaj'], funkcija (_) {

vrni {

moduleId: 'foo',

_ : _

});

// src / myapp.js

opredeli ([

'libs / jquery',

'ustnice / krmilo',

'src / utils'

], funkcija ($, krmilo, pripomočki) {

// Uporabi vsako od navedenih odvisnosti brez

// skrbi, če so tam ali ne.

$ ('div'). addClass ('bar');

// Poskrbljeno je tudi za odvisnosti

Utils ._. Tipke (okno);

});

To je odličen način za razvijanje modularnega JavaScript-a, ko se ukvarjate z veliko gibljivih delov in odvisnosti. Odgovornost za naročanje in vključitev skriptov je zdaj na plečih nalagalnika skriptov, tako da lahko preprosto navedete, kaj potrebujete, in začnete to uporabljati.

Po drugi strani pa obstaja nekaj potencialnih težav. Najprej imate na voljo dodatno knjižnico, ki jo lahko vključite in se naučite uporabljati. Nimam izkušenj s curl.js, vendar RequireJS vključuje učenje nastavitve konfiguracije za vaš projekt. Da se seznanite z nastavitvami, bo trajalo nekaj ur, nato pa bo pisanje začetne konfiguracije trajalo le nekaj minut. Tudi definicije modulov se lahko podaljšajo, če vodijo do kupa odvisnosti. Tu je primer, povzet iz razlage te težave v dokumentaciji RequireJS:

// Iz dokumentacije RequireJS:

// //requirejs.org/docs/whyamd.html#sugar

define (["zahtevaj", "jquery", "rezilo / objekt", "rezilo / fn", "rdapi",

"oauth", "rezilo / jig", "rezilo / url", "odprema", "računi",

"storage", "services", "widgets / AccountPanel", "widget / TabButton",

"widgets / AddAccount", "less", "osTheme", "jquery-ui-1.8.7.min",

"jquery.textOverflow"],

funkcija (zahtevajo, $, objekt, fn, rdapi,

oauth, jig, url, dispečers, računi,

shranjevanje, storitve, AccountPanel, TabButton,

AddAccount, manj, osTheme) {

});

Joj! RequireJS ponuja nekaj skladenjskega sladkorja, da se s tem spopade, kar je precej podobno drugemu priljubljenemu API-ju za modularni razvoj, CommonJS.

CJS (CommonJS)

Če ste kdaj napisali JavaScript na strani strežnika z uporabo Node.js, ste uporabili module CommonJS. Vsaka datoteka, ki jo napišete, ni zavita v kaj modnega, ima pa dostop do spremenljivke z imenomizvoz ki mu lahko dodelite vse, kar želite, da vam modul izpostavi. Evo, kako izgleda:

// 'zasebna' spremenljivka

var orderId = 123;

export.getOrderId = function () {

return orderId;

};

Potem, ko želite uporabiti modul, ga prijavite v vrstici:

// orderModule dobi vrednost 'izvoz'

var orderModule = require ('./ module-order');

orderModule.getOrderId (); // oceni na 123

Sintaktično se mi je to vedno zdelo boljše, predvsem zato, ker ne vključuje potratnih vdolbin, ki so prisotne v drugih možnostih, o katerih smo razpravljali. Po drugi strani pa se močno razlikuje od ostalih, saj je zasnovan za sinhrono nalaganje odvisnosti. Na strežniku je to bolj smiselno, na sprednjem delu pa ne. Sinhrono nalaganje odvisnosti pomeni daljši čas nalaganja strani, kar je za splet nesprejemljivo. Čeprav je CJS daleč moja sintaksa modula najljubšega videza, ga lahko uporabljam samo na strežniku (in med pisanjem mobilnih aplikacij s Appcelerator's Titanium Studio).

Eden, ki bo vladal vsem

Trenutni osnutek šeste izdaje ECMAScripta (ES6), specifikacija, iz katere je implementiran JavaScript, dodaja izvorno podporo za module. Specifikacija je še vedno v obliki osnutka, vendar je vredno pokukati, kako bi lahko izgledala prihodnost modularnega razvoja. Kar nekaj novih ključnih besed je uporabljenih v specifikacijah ES6 (znanih tudi kot Harmony), od katerih jih je več uporabljenih z moduli:

// libs / order-module.js

var orderId = 123;

izvoz var getOrderId = function () {

return orderId;

};

Kasneje ga lahko pokličete na več načinov:

uvoz {getOrderId} iz "libs / order-module";

getOrderId ();

Zgoraj izberete, kateri izvoz znotraj modula želite vezati na lokalne spremenljivke. Lahko pa uvozite celoten modul, kot da gre za objekt (podobno kotizvoz objekt v modulih CJS):

uvoz "libs / order-module" kot orderModule;

orderModule.getOrderId ();

Modulov ES6 je še veliko več (za več si oglejte spletni dnevnik dr. Axela Rauschmayerja 2ality), vendar bi vam primer moral pokazati nekaj stvari. Prvič, imamo sintakso, podobno modulom CJS, kar pomeni, da dodatne vdolbine ni nikjer, čeprav to ni vedno tako, kot boste našli na zgornji povezavi 2ality. Ob pogledu na primer ni očitno, še posebej zato, ker je zelo podoben CJS, to je, da so moduli, navedeni v izjavi o uvozu, naloženi asinhrono.

Končni rezultat je lahko berljiva skladnja CJS, pomešana z asinhrono naravo AMD. Na žalost bo minilo nekaj časa, preden bodo v celoti podprti v vseh pogosto ciljanih brskalnikih. Kljub temu pa se "nekaj časa" skrajšuje, saj prodajalci brskalnikov poostrijo svoje cikle izdaje.

Danes je kombinacija teh orodij prava pot pri modularnem razvoju JavaScript. Vse je odvisno od tega, kaj počnete. Če pišete knjižnico, uporabite vzorec oblikovanja modula. Če gradite aplikacije za brskalnik, uporabite module AMD s programom za nalaganje skriptov. Če ste na strežniku, izkoristite module CJS. Sčasoma bo ES6 seveda podprt vsesplošno - takrat lahko vse naredite na način ES6, ostalo pa odstranite!

Vprašanja ali misli? V oddelku za komentarje spodaj pustite sporočilo ali se obrnite na mene na Twitterju, @ freethejazz.

$config[zx-auto] not found$config[zx-overlay] not found