Welcome to Our Website

JavaScript-Fabrik Fungerer vs Constructor-Funktioner vs Klasser

Forud for ES6, der var en masse forvirring om forskellene mellem en fabrik funktion og en constructor-funktionen i JavaScript. Da ES6 har` klasse ‘ søgeord, en masse mennesker synes at tro, at løst mange problemer med konstruktør funktioner. Lad os undersøge de store forskelle, du stadig skal være opmærksom på.,

lad os Først se på eksempler af hver:

Hver af disse strategier butikker metoder på en delt prototype, og eventuelt støtter private data via constructor-funktion lukninger. Med andre ord, de har for det meste de samme funktioner, og kunne for det meste bruges om hverandre.

i JavaScript kan enhver funktion returnere et nyt objekt. Når det ikke er en konstruktørfunktion eller klasse, kaldes det en fabriksfunktion.,

ES6 klasser desugar til constructor-funktioner, så alt det, der følger om constructor-funktioner også gælder for ES6 klasser:

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

Konstruktører kraft opkald til at bruge new søgeord. Det er det, men det har nogle bivirkninger.

Så hvad gør new nøgleord?,

Bemærk: Vi vil bruge instance for at henvise til den nyoprettede eksempel, og Constructor for at henvise til constructor-funktion eller klasse, der har skabt eksempel.

  1. instantierer et nyt instansobjekt og binder this til det inden for konstruktøren.
  2. Binder instance.__proto__ til Constructor.prototype.
  3. Som en side-effekt af 2, binder instance.__proto__.constructor til Constructor.,
  4. implicit returnerer this, som henviser til instance.

fordele ved konstruktører & `klasse`

  • de fleste bøger lærer dig at bruge klasse eller konstruktører.
  • this henviser til det nye objekt.
  • nogle mennesker kan lide den måde myFoo = new Foo() læser.
  • der kan være en mikrooptimeringsydelse, men du bør ikke bekymre dig om det, medmindre du har profileret din kode og bevist, at det er et problem for dig.,

Ulemper af Konstruktører & `klasse`

Forud for ES6, at glemme new var en meget almindelig fejl. For at imødegå det, mange mennesker, bruges standardteksten til at håndhæve det:

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

I ES6+ (ES2015), hvis du forsøger at kalde en klasse konstruktør uden new, vil det altid smide en fejl. Det er ikke muligt at undgå at tvingenew krav til opkald uden at indpakke din klasse i en fabriksfunktion.,

detaljer om instantiering bliver lækket ind i den kaldende API (via det `nye` krav).

alle opkaldere er tæt koblet til konstruktørimplementeringen. Hvis du nogensinde har brug for fabrikkens ekstra fleksibilitet, er refactor en brudændring. Klasse at fabrikken refactors er fælles nok at de vises i den skelsættende Refactoring bog “Refactoring: Improving the Design of Existing Code” af Martin Fowler, Kent Beck, John Brant, William Opdyke, og Don Roberts.,

Konstruktører bryde Åbne / Lukkede Princippet

på Grund af det new krav, constructor-funktioner, der overtræder åbne/lukkede princip: en API bør være åbent for udvidelse, men lukket for modifikation.

jeg argumenterer for, at klassen til fabriksrefaktoren er almindelig nok til, at den skal betragtes som en standardudvidelse for alle konstruktører: opgradering fra en klasse til en fabrik bør ikke bryde ting, men i JavaScript gør det det.,

Hvis du starter ud eksport af en konstruktør eller en klasse, og brugerne begynder at bruge constructor, derefter ned på den vej, du indse, du har brug for fleksibilitet for en fabrik, (for eksempel, til at skifte gennemførelsen til at bruge objektet swimmingpools, eller til at instantiere på tværs udførelse sammenhænge, eller til at have flere arv fleksibilitet ved hjælp af alternative prototyper), ikke kan du nemt gøre det uden at tvinge en refactor på opkald.,

Desværre, i JavaScript, skifte fra en konstruktør eller klasse til en fabrik er en bryde ændring:

I eksemplet ovenfor, starter vi ud med en klasse, men vi vil tilføje mulighed for at tilbyde forskellige former for bil bundter. For at gøre det bruger fabrikken alternative prototyper til forskellige bilbundter. Jeg har brugt denne teknik til at gemme forskellige implementeringer af en medieafspillergrænseflade og vælge den rigtige prototype baseret på den type medie, som afspilleren har brug for til at kontrollere.,

brug af konstruktører muliggør den vildledende `instanceof`

en af de brydningsændringer i konstruktøren til fabriksrefaktoren er instanceof. Nogle gange er folk fristet til at bruge instanceof som en type check guard i deres kode. Det kan være meget problematisk. Jeg anbefaler, at du undgår instanceof.

`instanceof` løgne.,

instanceof ikke vil skrive, at kontrollere den måde, som du forventer tilsvarende kontrol at gøre i stærkt typet sprog. I stedet foretager den en identitetskontrol, der sammenligner objektets__proto__ objekt tilConstructor.prototype ejendom.

det vil ikke arbejde på tværs af forskellige hukommelse riger som iframes, for eksempel (en fælles kilde til fejl i 3.parts JavaScript integrerer). Det virker heller ikke, hvis dit Constructor.prototype bliver erstattet.,

Det vil også fejle, hvis du starter ud med en klasse eller en konstruktør (som returnerer this, der er knyttet til Constructor.prototype), og derefter skifte til at eksportere et vilkårligt objekt (som ikke er knyttet til Constructor.prototype), hvilket er, hvad der sker, når du ændrer fra en konstruktør til en fabrik.

kort sagt, instanceof er en anden måde, hvorpå skift fra en konstruktør til en fabrik er en brudændring.

fordele ved at bruge klasse

  • praktisk, selvstændig syntaks.,
  • en enkelt, kanonisk måde at efterligne klasser i JavaScript. Før ES6 var der flere konkurrerende implementeringer i populære biblioteker.
  • mere kendt for folk fra en klassebaseret sprogbaggrund.

ulemper ved at bruge klasse

alle konstruktør ulemper, plus:

  • fristelse for brugere til at oprette problematiske klassehierarkier ved hjælp afextends nøgleord.,

Klassehierarkier fører til en masse velkendte problemer i objektorienteret design, herunder det skrøbelige baseklasseproblem, gorilla banana-problemet, duplikering af nødvendighedsproblem og så videre. Desværre giver klassen strækker sig som bolde råd til at kaste og stole råd til at sidde. For mere, læs “de to søjler i JavaScript: Prototypal OO” og “inde i Dev Team Death Spiral”.,

det er værd at bemærke, at både konstruktører og fabrikker også kan bruges til at skabe problematiske arvehierarkier, men med nøgleordet `udvider` skaber klassen en overkommelighed, der fører dig ned ad den forkerte vej. Med andre ord, det opfordrer dig til at tænke i form af ufleksible (og ofte forkert) er-et forhold, snarere end den mere fleksible kompositoriske har-A eller kan-gøre relationer.

en overkommelighed er en funktion, der giver mulighed for at udføre en bestemt handling., For eksempel, en knop giver vride et håndtag giver trække en knap giver trykke på osv…

Fordele ved at Bruge Fabrikker

Fabrikker er meget mere fleksible end enten constructor-funktioner eller-klasser, og de behøver ikke lede mennesker ad den forkerte sti, ved at friste dem med `udvider` søgeord og dybt arv hierarkier. Der er mange sikrere kode genbrug mekanismer, du bør favorisere over klasse arv, herunder funktioner og moduler.,

Returnere enhver vilkårlig objekt og bruge alle vilkårlige prototype

For eksempel, kan du nemt oprette forskellige typer af objekter, der implementerer det samme API, fx, en medieafspiller, der kan instantiere spillere for flere typer af video-indhold, som bruger forskellige Api ‘ er under motorhjelmen, eller en begivenhed, bibliotek, som kan udsende DOM begivenheder eller web socket begivenheder.

Fabrikker kan også instantiere objekter på tværs udførelse sammenhænge, drage fordel af objekt swimmingpools, og give mulighed for mere fleksibel prototypal arv modeller.,

ingen refactoring bekymringer

du ville aldrig have behov for at konvertere fra en fabrik til en konstruktør, så refactoring vil aldrig være et problem.

ingen”ny”

ingen tvetydighed om at bruge new. Ikke. (det vil gøre this opfører sig dårligt, se næste punkt).

Standard `dette` adfærd

this opfører sig, som det normalt ville, så du kan bruge det til at få adgang til det overordnede objekt. For eksempel inde player.create(), this refererer til spiller, ligesom enhver anden metode påkaldelse ville., call() og apply() også overflytte this som forventet.

Nogle mennesker kan godt lide den måde `myFoo = createFoo()` læser

  • ikke lave et link fra instans til Factory.prototype — men det er faktisk en god ting, fordi du ikke vil få en vildledende instanceof. I stedet vil instanceof altid mislykkes. Se fordele.
  • this henviser ikke til det nye objekt inde i fabrikken. Se fordele.,
  • det kan udføre langsommere end en konstruktør funktion i mikro-optimering benchmarks. Den langsomme vej er stadig meget hurtig-millioner af ops / SEK på en gammel computer. Dette er mere sandsynligt, at det er et problem i bibliotek eller rammekode end i applikationskode. Benchmark altid fra brugerperspektivet, før du bruger mikrooptimeringer.

Konklusion

efter min mening, class kan have en praktisk syntaks, men det kan ikke gøre op for det faktum, at det lokker uforsigtige brugere til at gå ned på klipperne klasse arv., Det er også risikabelt, fordi der i fremtiden, kan du overveje at opgradere til en fabrik, men alle dine opkald vil blive tæt koblet til constructor-funktion på grund af new søgeord og det faktum, at flytte fra klasser til fabrikker er en bryde ændre.

du tænker måske, at du bare kan refactor opkaldssiderne, men på store hold, eller hvis den klasse, du arbejder med, er en del af et offentligt API, kan du bryde kode, der ikke er i din kontrol. Med andre ord kan du ikke altid antage, at refactoring-opkald endda er en mulighed.,

Det fede ved fabrikker er, at de er ikke bare mere effektivt og mere fleksibelt, de er også den nemmeste måde at tilskynde til hele hold, og hele API-bruger baser til at bruge mønstre, der er enkle, fleksible og sikre.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *