Welcome to Our Website

JavaScript Factory Functions vs Constructor Functions vs Classes (Română)

înainte de ES6, a existat o mulțime de confuzie cu privire la diferențele dintre o funcție fabrică și o funcție constructor în JavaScript. Deoarece ES6 are cuvântul cheie „clasă”, o mulțime de oameni par să creadă că au rezolvat multe probleme cu funcțiile constructorului. Nu a făcut-o. să explorăm diferențele majore de care încă trebuie să fii conștient.,fiecare dintre aceste strategii stochează metode pe un prototip partajat și, opțional, acceptă date private prin închideri de funcții ale constructorului. Cu alte cuvinte, ele au în mare parte aceleași caracteristici și ar putea fi folosite în mod interschimbabil.

în JavaScript, orice funcție poate returna un obiect nou. Când nu este o funcție sau o clasă de constructor, se numește o funcție de fabrică.,

ES6 clase desugar să constructor funcții, astfel încât tot ceea ce urmează despre constructor funcții, de asemenea, se aplică la ES6 clase:

class Foo {}console.log(typeof Foo); // function

Constructori vigoare apelanții să utilizați new cuvinte cheie. Asta e, dar asta are unele efecte secundare relevante.

Deci, ce face cuvântul cheie new?,

Nota: Vom folosi instance pentru a se referi la nou creat exemplu, și Constructor să se refere la funcția de constructor sau de clasa care a creat exemplu.

  1. Instanțiază un nou exemplu de obiect și se leagă this la acesta, în constructor.
  2. leagă instance.__proto__la Constructor.prototype.
  3. ca efect secundar al 2, se leagă instance.__proto__.constructor la Constructor.,
  4. Implicit se întoarce this, care se referă la instance.

beneficiile Constructorilor & `class`

  • cele mai multe cărți vă învață să utilizați clasa sau Constructori.
  • this se referă la noul obiect.
  • Unora le place modulmyFoo = new Foo() citește.
  • poate exista un beneficiu de performanță de micro-optimizare, dar nu trebuie să vă faceți griji cu privire la acest lucru decât dacă ați profilat codul dvs. și ați dovedit că este o problemă pentru dvs.,

Dezavantaje ale Constructorilor & „clasa”

Înainte de a ES6, uitând new a fost un bug comun. Pentru a contracara aceasta, mulți oameni au folosit șabloane pentru a pune în aplicare:

function Foo() {
if (!(this instanceof Foo)) { return new Foo(); }
}

În ES6+ (ES2015) dacă încercați pentru a apela un constructor de clasă fără new, întotdeauna va arunca o eroare. Nu este posibil să evitați forțarea cerinței new pentru apelanți fără a împacheta clasa într-o funcție din fabrică.,

detaliile instanțierii se scurg în API-ul de apelare (prin cerința „nouă”).

toți apelanții sunt strâns cuplați la implementarea constructorului. Dacă aveți vreodată nevoie de flexibilitatea suplimentară a fabricii, refactorul este o schimbare de rupere. Clasa a fabrica refactors sunt destul de comune care apar în seminale Refactoring carte, „Refactorizare: Îmbunătățirea Design de Cod Existent” de Martin Fowler, Kent Beck, John Brant, William Opdyke, și Nu Roberts.,

Constructori rupe Deschis / Închis Principiu,

Pentru new cerință, constructor funcții incalca deschis/închis principiu: un API ar trebui să fie deschise pentru extindere, dar închise pentru modificări.

susțin că refactorul class to factory este destul de comun încât ar trebui considerat o extensie standard pentru toți constructorii: actualizarea de la o clasă la o fabrică nu ar trebui să rupă lucrurile, dar în JavaScript, o face.,

Dacă începi exportatoare de un constructor sau de clasă și utilizatorii începe să utilizați constructorul, apoi pe drum îți dai seama că ai nevoie de flexibilitatea de a o fabrica, (de exemplu, pentru a comuta la punerea în aplicare a folosi obiect piscine, sau pentru a instantia peste execuție contexte, sau de a avea mai mult moștenire flexibilitate în utilizarea unor prototipuri), nu puteți face cu ușurință fără a forța un refactor pe apelanți.,

din Păcate, în JavaScript, trecerea de la un constructor sau de clasă de la o fabrica este o rupere de schimbare:

În exemplul de mai sus, vom începe cu o clasă, dar vrem să adăugați capacitatea de a oferi diferite tipuri de mașini de pachete. Pentru a face acest lucru, fabrica folosește prototipuri alternative pentru diferite pachete auto. Am folosit această tehnică pentru a stoca diverse implementări ale unei interfețe media player, alegând prototipul corect în funcție de tipul de media pe care playerul trebuia să îl controleze.,

utilizarea Constructorilor permite „instanceof” înșelător

una dintre modificările de rupere în constructor la refactor din fabrică este instanceof. Uneori, oamenii sunt tentați să folosească instanceof ca o gardă de verificare de tip în codul lor. Acest lucru poate fi foarte problematic. Vă recomandăm să evitați instanceof.

„instanceof” minciuni.,

instanceof nu face acest tip de verificare modul în care te aștepți similare verificările, în puternic tastat limbi. În schimb, face o verificare a identității comparând obiectul __proto__ cu proprietatea Constructor.prototype.

nu va funcționa pe diferite tărâmuri de memorie, cum ar fi iframe-urile, de exemplu (o sursă comună de bug-uri în încorporările JavaScript 3rd party). De asemenea, nu funcționează dacă Constructor.prototype este înlocuit.,

de asemenea, va eșua dacă începe cu o clasă sau constructor (care revine this, legate de Constructor.prototype), și apoi trece la exportarea unui obiect arbitrar (nu sunt legate de Constructor.prototype), care este ceea ce se întâmplă atunci când vă schimbați de la un constructor la o fabrică.

pe scurt, instanceof este un alt mod în care trecerea de la un constructor la o fabrică este o schimbare de rupere.

beneficiile utilizării clasei

  • sintaxă convenabilă, autonomă.,
  • un singur mod canonic de a emula clase în JavaScript. Înainte de ES6, au existat mai multe implementări concurente în bibliotecile populare.
  • mai familiar pentru oameni dintr-un fundal de limbă bazată pe clasă.

dezavantaje ale utilizării clasei

toate dezavantajele constructorului, plus:

  • tentația utilizatorilor de a crea ierarhii de clasă problematice folosind cuvântul cheieextends.,ierarhiile claselor conduc la o grămadă de probleme bine cunoscute în proiectarea orientată pe obiecte, inclusiv problema fragilă a clasei de bază, problema Gorilla banana, duplicarea prin problema necesității și așa mai departe. Din păcate, clasa oferă se extinde ca bile permite aruncarea și scaune permite ședinței. Pentru mai multe, citiți „cei doi Piloni ai JavaScript: Prototypal OO”și” Inside the Dev Team Death Spiral”.,

    este demn de remarcat faptul că atât Constructorii, cât și fabricile pot fi de asemenea utilizate pentru a crea ierarhii de moștenire problematice, dar cu cuvântul cheie „extends”, clasa creează o accesibilitate care vă conduce pe calea greșită. Cu alte cuvinte, vă încurajează să gândiți în termeni de relații inflexibile (și adesea greșite) is-a, mai degrabă decât relațiile compoziționale mai flexibile has-a sau can-do.

    o accesibilitate este o caracteristică care oferă posibilitatea de a efectua o anumită acțiune., De exemplu, un buton permite răsucirea, o pârghie permite tragerea, un buton oferă presare, etc…

    Beneficiile de a Utiliza Fabrici

    Fabrici sunt mult mai flexibile decât oricare constructor funcții sau clase, și ei nu-i conduce pe oameni pe o cale greșită, tentându-i cu `extinde` cuvinte cheie și profundă moștenire ierarhii. Există multe mecanisme mai sigure de reutilizare a codului pe care ar trebui să le favorizați asupra moștenirii clasei, inclusiv funcții și module.,de exemplu, puteți crea cu ușurință diferite tipuri de obiecte care implementează același API, de exemplu, un player media care poate instantia Playere pentru mai multe tipuri de conținut video care utilizează diferite API-uri sub capotă sau o bibliotecă de evenimente care poate emite evenimente DOM sau evenimente socket web.

    fabricile pot, de asemenea, să instanțieze obiecte în contexte de execuție, să profite de bazinele de obiecte și să permită modele de moștenire prototipice mai flexibile.,nu veți avea niciodată nevoie să convertiți dintr-o fabrică într-un constructor, deci refactorizarea nu va fi niciodată o problemă.

    Nu `nou”

    nu ambiguitate despre utilizarea new. Nu. (se va face this se comporta prost, a se vedea punctul următor).

    standard „acest” comportament

    this se comportă așa cum ar fi în mod normal, astfel încât să puteți utiliza pentru a accesa obiectul părinte. De exemplu, în interiorul player.create(), this se referă la player, la fel ca orice altă metodă de invocare ar., call() și apply(), de asemenea, de a realoca this cum era de așteptat.

    Unii oameni place cum `myFoo = createFoo()` citește

    • nu crea un link de exemplu la Factory.prototype — dar aceasta este de fapt un lucru bun pentru că nu va primi un înșelătoare instanceof. În schimb, instanceof va eșua întotdeauna. Vezi beneficii.
    • this nu se referă la noul obiect din fabrică. Vezi beneficii.,
    • se poate efectua mai lent decât o funcție constructor în Repere de micro-optimizare. Calea lentă este încă foarte rapidă-milioane de ops / sec pe un computer vechi. Acest lucru este mai probabil să fie o preocupare în bibliotecă sau cod cadru decât în codul aplicației. Benchmark întotdeauna din perspectiva utilizatorului înainte de a utiliza micro-optimizări.

    Concluzie

    În opinia mea, class poate avea un convenabil sintaxa, dar asta nu compensa faptul că acesta atrage utilizatorii nevigilent să se prăbușească pe roci de clasa de moștenire., Este, de asemenea, riscant, deoarece, în viitor, poate doriți să faceți upgrade la o fabrică, dar toți cei care vor fi strâns legate de funcția de constructor pentru a new cuvinte cheie și de faptul că trecerea de la clase la fabrici este o rupere de schimbare.

    s-ar putea să vă gândiți că puteți doar să refactorați site-urile de apeluri, dar pe echipe mari sau dacă clasa cu care lucrați face parte dintr-un API public, puteți sparge codul care nu este în controlul dvs. Cu alte cuvinte, nu puteți presupune întotdeauna că refactorizarea apelanților este chiar o opțiune.,lucrul interesant despre fabrici este că nu sunt doar mai puternice și mai flexibile, ci și cel mai simplu mod de a încuraja echipe întregi și baze întregi de utilizatori API să utilizeze modele care sunt simple, flexibile și sigure.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *