Programmēšana

Kodējiet JavaScript viedā, modulārā veidā

Daži cilvēki joprojām šķiet pārsteigti, ka JavaScript tiek uzskatīts par cienījamu, pieaugušo programmēšanas valodu nopietnām lietojumprogrammām. Faktiski JavaScript izstrāde ir nobriedusi gadiem ilgi, un paraugs ir moduļu izstrādes paraugprakse.

Moduļkodu rakstīšanas priekšrocības ir labi dokumentētas: lielāka uzturēšana, izvairīšanās no monolītajiem failiem un koda atsaistīšana vienībās, kuras var pārbaudīt pareizi. Tiem no jums, kuri vēlas ātri nokļūt, šeit ir izplatītākā mūsdienu JavaScript izstrādātāju prakse moduļu koda rakstīšanai.

Moduļa modelis

Sāksim ar pamata dizaina modeli, ko sauc par moduļa modeli. Kā jums varētu būt aizdomas, tas ļauj mums rakstīt kodu modulāri, ļaujot mums aizsargāt konkrēto moduļu izpildes kontekstu un globāli atklāt tikai to, ko mēs vēlamies pakļaut. Modelis izskatās apmēram šādi:

(funkcija () {

// 'privāts' mainīgais

var orderId = 123;

// atmaskot metodes un mainīgos, tos piesaistot

// uz globālo objektu

window.orderModule = {

getOrderId: funkcija () {

// jums atnesa aizvērumi

atgriešanas orderId;

}

};

})()

Anonīmsfunkciju izteiksme, kas šajā gadījumā darbojas kā rūpnīca, tiek uzrakstīta un nekavējoties izsaukta. Ātruma labad jūs varat nepārprotami pārsūtīt mainīgos uzfunkciju izsaukt, faktiski mainot šos mainīgos vietējā mērogā. Jūs dažreiz to redzēsiet kā aizsardzības manevru bibliotēkās, kas atbalsta vecās pārlūkprogrammas, kurās noteiktas vērtības (piemēram,nenoteikts) ir rakstāmas īpašības.

(funkcija (globāla, nedefinēta) {

// šeit esošais kods var ātri piekļūt globālajam objektam,

// un 'undefined' noteikti būs 'undefined'

// PIEZĪME: Mūsdienu pārlūkprogrammās “undefined” nav rakstāms,

// bet ir vērts to paturēt prātā

// rakstot kodu vecajām pārlūkprogrammām.

}) (šis)

Tas ir tikai dizaina modelis. Izmantojot šo paņēmienu, lai rakstītu modulāru JavaScript, jums nav jāiekļauj papildu bibliotēkas. Atkarību trūkums dažos iestatījumos ir liels plus (vai kritisks uzdevums), it īpaši, ja rakstāt bibliotēku. Jūs redzēsiet, ka lielākā daļa populāro bibliotēku izmantos šo modeli, lai iekapsulētu iekšējās funkcijas un mainīgos, atklājot tikai nepieciešamo.

Tomēr, ja jūs rakstāt pieteikumu, šai pieejai ir daži trūkumi. Pieņemsim, ka jūs izveidojat moduli, kurā iestatītas dažas metodeslogs.pasūtījumi. Ja vēlaties izmantot šīs metodes citās lietojumprogrammas daļās, pirms zvanīšanas tām jāpārliecinās, vai modulis ir iekļauts. Pēc tam tajā kodā, uz kuru zvanātwindow.orders.getOrderId, jūs uzrakstāt kodu un cerat, ka otrs skripts ir ielādēts.

Tas, iespējams, nešķiet pasaules gals, bet tas var ātri iziet no sarežģītu projektu kontroles - un skriptu iekļaušanas kārtības pārvaldīšana kļūst par sāpēm. Turklāt visiem failiem jābūt sinhroni ielādētiem, pretējā gadījumā jūs uzaicināsiet sacensību apstākļus, lai salauztu kodu. Ja tikai būtu veids, kā skaidri deklarēt moduļus, kurus vēlaties izmantot dotajam koda bitam ....

AMD (asinhronā moduļa definīcija)

AMD radās tāpēc, ka bija jānorāda skaidras atkarības, vienlaikus izvairoties no visu skriptu sinhronas ielādes. To ir viegli izmantot pārlūkprogrammā, taču tā nav dzimtā, tāpēc jāiekļauj bibliotēka, kas veic skriptu ielādi, piemēram, RequireJS vai curl.js. Lūk, kā izskatās moduļa noteikšana, izmantojot AMD:

// libs / order-module.js

definēt (funkcija () {

// 'privāts' mainīgais

var orderId = 123;

// atmaskot metodes un mainīgos, tos atgriežot

atgriezties {

getOrderId: funkcija () {

atgriešanas orderId;

}

});

Tas izskatās līdzīgi tam, ar ko mums bija darīšana iepriekš, izņemot to, ka tā vietā, lai uzreiz izsauktu mūsu rūpnīcas funkciju, mēs to nododam kā argumentudefinēt. Īstā burvība sākas tad, kad vēlāk vēlaties izmantot moduli:

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

orderModule.getOrderId (); // novērtē līdz 123

});

Pirmais argumentsdefinēt tagad ir atkarību masīvs, kas var būt patvaļīgi garš, un rūpnīcas funkcija uzskaita formālos parametrus tām atkarībām, kas tam jāpievieno. Tagad dažām jums nepieciešamajām atkarībām var būt atsevišķas atkarības, taču, izmantojot AMD, jums tas nav jāzina:

// src / utils.js

definēt (['libs / pasvītrojums'], funkcija (_) {

atgriezties {

moduleId: 'foo',

_ : _

});

// src / myapp.js

definēt ([

"libs / jquery",

"libs / stūre",

'src / utils'

], funkcija ($, Stūres, Utils) {

// Izmantojiet katru no norādītajām atkarībām bez

// uztraucoties, vai viņi tur ir vai nav.

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

// Aprūpētas arī pakārtotās atkarības

Izmanto ._. Taustiņus (logs);

});

Tas ir lielisks veids, kā izstrādāt moduļu JavaScript, strādājot ar daudzām kustīgām detaļām un atkarībām. Atbildība par skriptu pasūtīšanu un iekļaušanu tagad gulstas uz skriptu ielādētāja pleciem, ļaujot jums vienkārši norādīt, kas jums nepieciešams, un sākt to izmantot.

No otras puses, ir daži potenciālie jautājumi. Pirmkārt, jums ir papildu bibliotēka, kuru iekļaut un iemācīties izmantot. Man nav pieredzes ar curl.js, bet RequireJS ietver mācīšanos, kā iestatīt konfigurāciju savam projektam. Tas prasīs dažas stundas, lai iepazītos ar iestatījumiem, pēc tam sākotnējās konfigurācijas rakstīšanai vajadzētu aizņemt tikai minūtes. Arī moduļu definīcijas var kļūt garākas, ja tās noved pie atkarību kaudzes. Šis piemērs ir ņemts no šīs problēmas skaidrojuma RequireJS dokumentācijā:

// No RequireJS dokumentācijas:

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

definēt (["pieprasīt", "jquery", "asmens / objekts", "asmens / fn", "rdapi",

"oauth", "blade / jig", "asmens / url", "nosūtīšana", "konti",

"krātuve", "pakalpojumi", "logrīki / AccountPanel", "logrīki / TabButton",

"logrīki / AddAccount", "mazāk", "osTheme", "jquery-ui-1.8.7.min",

"jquery.textOverflow"],

funkcija (pieprasīt, $, objekts, fn, rdapi,

oauth, jig, url, dispatch, accounts,

krātuve, pakalpojumi, AccountPanel, TabButton,

AddAccount, mazāk, osTheme) {

});

Ai! Lai to risinātu, RequireJS nodrošina sintaktisko cukuru, kas izskatās diezgan līdzīgs vēl vienam populāram modulāro izstrādes API CommonJS.

CJS (CommonJS)

Ja kādreiz esat rakstījis servera puses JavaScript, izmantojot Node.js, esat izmantojis CommonJS moduļus. Katrs jūsu rakstītais fails nav iesaiņots nevienā iedomātā, bet tam ir piekļuve mainīgajam, ko sauceksports kam jūs varat piešķirt visu, ko vēlaties moduļa pakļaut. Lūk, kā tas izskatās:

// mainīgais “privāts”

var orderId = 123;

export.getOrderId = funkcija () {

atgriešanas orderId;

};

Tad, kad vēlaties izmantot moduli, jūs paziņojat, ka tas ir iekļauts:

// orderModule iegūst “eksporta” vērtību

var orderModule = pieprasīt ('./ order-module');

orderModule.getOrderId (); // novērtē līdz 123

Sintaktiski tas man vienmēr ir izskatījies labāk, galvenokārt tāpēc, ka tas neietver izšķērdīgu atkāpi citās pārrunātajās opcijās. No otras puses, tas ļoti atšķiras no citiem, jo ​​ir paredzēts sinhronai atkarību ielādēšanai. Tas ir jēgpilnāk serverī, bet tas nedarīs priekšējā galā. Sinhronā atkarības ielāde nozīmē ilgāku lapas ielādes laiku, kas tīmeklim nav pieņemams. Lai gan CJS ir neapšaubāmi mana iecienītākā moduļa sintakse, es to varu izmantot tikai serverī (un, rakstot mobilās lietotnes ar Appcelerator's Titanium Studio).

Viens, kas tos visus pārvalda

Pašreizējais ECMAScript sestā izdevuma (ES6) projekts, spec, no kura tiek ieviests JavaScript, papildina moduļu vietējo atbalstu. Specifikācija joprojām ir melnraksta formā, taču ir vērts palūkoties, kāda varētu būt moduļu izstrādes nākotne. ES6 specifikācijā (pazīstama arī kā Harmony) tiek izmantoti diezgan daudz jaunu atslēgvārdu, no kuriem vairāki tiek izmantoti kopā ar moduļiem:

// libs / order-module.js

var orderId = 123;

eksportēt var getOrderId = funkcija () {

atgriešanas orderId;

};

Vēlāk to var piezvanīt vairākos veidos:

importēt {getOrderId} no "libs / order-module";

getOrderId ();

Iepriekš izvēlaties, kuru moduļa eksportu vēlaties saistīt ar lokālajiem mainīgajiem. Alternatīvi, jūs varat importēt visu moduli tā, it kā tas būtu objekts (līdzīgi kāeksports objekts CJS moduļos):

importēt "libs / order-module" kā orderModule;

orderModule.getOrderId ();

ES6 moduļiem ir daudz vairāk (vairāk skatiet Dr Axel Rauschmayer 2ality blogā), taču piemērā jums vajadzētu parādīt dažas lietas. Pirmkārt, mums ir sintakse, kas līdzīga CJS moduļiem, kas nozīmē, ka papildu ievilkums nekur nav atrodams, lai gan tas ne vienmēr notiek, kā jūs atradīsit iepriekš minētajā saitē 2ality. Kas nav acīmredzams, aplūkojot piemēru, jo īpaši tāpēc, ka tas izskatās tik daudz kā CJS, ir tas, ka importa paziņojumā uzskaitītie moduļi tiek ielādēti asinhroni.

Gala rezultāts ir viegli nolasāma CJS sintakse, kas sajaukta ar AMD asinhrono raksturu. Diemžēl pēc kāda laika tie tiks pilnībā atbalstīti visās pārlūkprogrammās, kurām parasti ir mērķauditorija. Tas nozīmē, ka "kādu laiku" arvien vairāk un mazāk, jo pārlūku pārdevēji pastiprina izlaišanas ciklus.

Mūsdienās šo rīku kombinācija ir veids, kā iet uz moduļu JavaScript izstrādi. Viss ir atkarīgs no tā, ko jūs darāt. Ja rakstāt bibliotēku, izmantojiet moduļa noformējuma modeli. Ja veidojat lietojumprogrammas pārlūkprogrammai, izmantojiet AMD moduļus ar skriptu ielādētāju. Ja atrodaties serverī, izmantojiet CJS moduļu priekšrocības. Galu galā, protams, ES6 tiks atbalstīts visā pasaulē - tajā brīdī jūs varat darīt lietas, kas saistītas ar ES6, un pārējās pārmest!

Jautājumi vai domas? Jūtieties brīvi atstāt ziņojumu komentāru sadaļā vai sazināties ar mani Twitter, @ freethejazz.

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