előtt ES6, volt egy csomó zavart a különbség a gyári funkció és a konstruktor függvény JavaScript. Mivel az ES6 rendelkezik az “osztály” kulcsszóval, sok ember úgy gondolja, hogy sok problémát megoldott a konstruktor funkciókkal. Fedezzük fel azokat a főbb különbségeket, amelyekről még mindig tisztában kell lenned.,
Először is, nézzük a példákat az egyes:
Minden ilyen stratégiák üzletek módszerek közös prototípus, valamint opcionálisan támogatja a személyes adatok keresztül konstruktor függvény lezárások. Más szóval, ezek többnyire azonos tulajdonságokkal, és többnyire felcserélhető.
a JavaScriptben bármely funkció visszatérhet egy új objektumhoz. Ha ez nem egy konstruktor függvény vagy osztály, ez az úgynevezett gyári függvény.,
ES6 osztályok desugar, hogy a konstruktor függvények, tehát minden, ami a következőképpen szól konstruktor függvények is vonatkozik ES6 osztályok:
class Foo {}console.log(typeof Foo); // function
Konstruktőri erő hívók, hogy használja a new
kulcsszó. Ez az, de ennek vannak releváns mellékhatásai.
tehát mit csinál a new
kulcsszó?,
megjegyzés: a
instance
hivatkozni fogunk az újonnan létrehozott példányra, ésConstructor
hivatkozni a konstruktor függvényre vagy osztályra, amely létrehozta a példányt.
- Instantiates a new instance object and constructing
this
to it within the constructor. -
instance.__proto__
Constructor.prototype
. - 2 mellékhatásaként
instance.__proto__.constructor
Constructor
kötődik., - implicit módon visszaadja a
this
értéket, amely ainstance
– ra utal.
A konstruktorok előnyei & “osztály”
- a legtöbb könyv tanítja az osztály vagy a konstruktorok használatát.
-
this
az új objektumra utal. - vannak, akik szeretik az utat
myFoo = new Foo()
olvas. - előfordulhat, hogy egy mikro-optimalizálási teljesítmény előny, de nem kell aggódnia, hogy ha nem profilozott a kódot, és bebizonyította, hogy ez egy probléma az Ön számára.,
& `class`
előtt ES6, elfelejtve new
volt egy nagyon gyakori hiba. Ennek ellensúlyozására sokan boilerplate-et használtak annak érvényesítésére:
function Foo() {
if (!(this instanceof Foo)) { return new Foo(); }
}
az ES6+ – ban (ES2015) ha megpróbál hívni egy osztály konstruktort new
nélkül, akkor mindig hibát fog dobni. Nem lehet elkerülni a new
követelmény kényszerítését a hívókra anélkül, hogy az osztályt gyári funkcióba csomagolná.,
A példányosítás részletei kiszivárogtak a hívó API-ba (az ” új ” követelményen keresztül).
minden hívó szorosan kapcsolódik a kivitelező végrehajtásához. Ha valaha is szüksége van a gyár további rugalmasságára,a refactor törés. Osztály a gyári refaktorok elég gyakori, hogy megjelennek a seminal Refactoring book, “Refactoring: javítása a Design meglévő kód” Martin Fowler, Kent Beck, John Brant, William Opdyke, Don Roberts.,
A konstruktorok anew
követelmény miatt megszakítják a nyitott/zárt elvet, a konstruktor funkciók megsértik a nyitott/zárt elvet: az API-nak nyitottnak kell lennie a kiterjesztéshez, de módosításhoz zárva kell lennie.
azt állítják, hogy az osztály gyári refactor elég gyakori, hogy figyelembe kell venni a standard kiterjesztés minden konstruktorok: frissítés egy osztály a gyár nem törik a dolgokat, de a JavaScript, ez nem.,
Ha elindul exportáló egy kivitelező vagy az osztály, illetve a felhasználók kezdje meg a kivitelező, akkor az úton tudod, hogy kell a rugalmasság a gyári, (például, hogy a kapcsoló a végrehajtás használható tárgy, medencék, vagy létrehozni az egész kivégzés kontextusokban, vagy több örökség rugalmasság segítségével alternatív prototípusok), nem lehet olyan könnyen megtenni, anélkül, hogy arra kényszerítve a refactor a hívó.,
Sajnos, a JavaScript ki, akkor az átállás a kivitelező, vagy az osztály, hogy egy gyár egy törés változás:
a fenti példában, akkor elindul egy osztály, de szeretnénk hozzáadni a képesség, hogy az ajánlat különböző típusú autó kötegek. Ehhez a gyár alternatív prototípusokat használ különböző autócsomagokhoz. Ezt a technikát használtam egy médialejátszó felület különböző megvalósításainak tárolására, a megfelelő prototípus kiválasztása a lejátszó vezérléséhez szükséges adathordozó típusa alapján.,
A konstruktorok használata lehetővé teszi a megtévesztő ‘instanceof’
a konstruktor egyik törésváltozása a gyári refactorra instanceof
. Néha az emberek a kísértés, hogy használja ainstanceof
, mint egy Típus ellenőrző őr a kódot. Ez nagyon problematikus lehet. Azt javasoljuk, hogy ne instanceof
.
`instanceof` lies.,
nem írja be, hogy hasonló ellenőrzésekre számít-e ehhez erősen gépelt nyelveken. Ehelyett egy identitásellenőrzést végez, amely összehasonlítja az objektum __proto__
objektumát a Constructor.prototype
tulajdonsággal.
nem fog működni a különböző memóriahelyeken, például az iframes-en (például a 3rd party JavaScript beágyazások hibáinak gyakori forrása). Nem működik, ha a Constructor.prototype
helyébe lép.,
Ez akkor is sikertelen lesz, ha egy osztály vagy konstruktorral indul (amely a this
– hoz kapcsolódik, a Constructor.prototype
), majd átvált egy tetszőleges objektum exportálására (nem kapcsolódik a Constructor.prototype
), ami akkor történik, ha egy konstruktorról egy gyár.
röviden, instanceof
egy másik módja annak, hogy a konstruktorról a gyárra váltás törés.
A
- kényelmes, önálló szintaxis használatának előnyei.,
- egyetlen, kanonikus módon emulálni osztályok JavaScript. Az ES6 előtt számos versengő megvalósítás volt a népszerű könyvtárakban.
- ismertebb, hogy az emberek egy osztály-alapú nyelvi háttér.
az osztály
összes konstruktor hátránya, plusz:
- kísértés a felhasználók számára, hogy problémás osztályhierarchiákat hozzanak létre a
extends
kulcsszó segítségével.,
osztály hierarchiák vezet egy csomó jól ismert problémák objektum-orientált tervezés, beleértve a törékeny bázis osztály probléma, a gorilla banán probléma, a párhuzamos szükségszerűség probléma, stb. Sajnos, az osztály olyan, mint a labdák, a dobás és a székek megengedik maguknak, hogy üljenek. További információ: “the Two Pillars of JavaScript: Prototypal OO” and “Inside the Dev Team Death Spiral”.,
érdemes megjegyezni, hogy mind a konstruktorok, mind a gyárak problémás öröklési hierarchiák létrehozására is használhatók, de az “extends” kulcsszóval az osztály olyan megengedhetőséget hoz létre, amely rossz úton vezet. Más szóval, arra ösztönzi, hogy úgy gondolja, rugalmatlan (és gyakran rossz)-a kapcsolatok, hanem a rugalmasabb kompozíciós van-a vagy can-do kapcsolatok.
egy olyan funkció, amely lehetővé teszi egy bizonyos művelet végrehajtását., Például, egy gomb biztosít kanyargó, egy kart nyújt húzza, egy gomb biztosít nyomja, stb…
Előnyökkel jár, ha a Gyárak
a Gyárak sokkal rugalmasabb, mint akár konstruktor függvények vagy osztályok, illetve nem vezetnek le az embereket a rossz utat, csábító őket a `kiterjeszti` kulcsszót, majd mély öröklési hierarchia. Számos biztonságosabb kód újrafelhasználási mechanizmus létezik, amelyeket előnyben kell részesítenie az osztály öröklésével szemben, beleértve a funkciókat és a modulokat is.,
Vissza tetszőleges objektum használata tetszőleges prototípus
például egyszerűen készíthet a különböző típusú tárgyakat, amelyek végrehajtása ugyanaz API, pl. médialejátszó, amely képes létrehozni a játékosok több típusú videó tartalmakat, amelyek különböző Api-k a motorháztető alatt, vagy az esemény könyvtár, amely bocsát ki DOM események vagy web socket események.
a gyárak a végrehajtási kontextusokban is példányosíthatnak objektumokat, kihasználhatják az objektumkészleteket, valamint rugalmasabb prototípusos öröklési modelleket is lehetővé tehetnek.,
Nem, írd újra gond
soha nem kell átalakítani a gyár, hogy egy kivitelező, akkor írd újra, soha nem lesz probléma.
nincs”új”
nincs kétértelműség anew
használatával kapcsolatban. (A this
rosszul viselkedik, lásd a következő pontot).
Standard “this”behavior
this
úgy viselkedik, mint általában, így használhatja a szülő objektum eléréséhez. Például belül player.create()
, this
utal játékos, mint bármely más módszer meghívás lenne., call()
és apply()
a várakozásoknak megfelelően a this
– t is áthelyezi.
vannak, akik szeretik `ahogy ‘myFoo = createFoo ()’ olvas
- nem hoz létre linket a példányból a
Factory.prototype
– de ez valójában jó dolog, mert nem kap egy megtévesztőinstanceof
. Ehelyett ainstanceof
mindig sikertelen lesz. Lásd előnyök. -
this
nem utal a gyáron belüli új objektumra. Lásd előnyök., - a mikro-optimalizálási referenciaértékekben lassabb lehet, mint a konstruktor függvény. A lassú út még mindig nagyon gyors – millió ops / sec egy régi számítógépen. Ez nagyobb valószínűséggel aggodalomra ad okot a könyvtárban vagy a keretkódban, mint az alkalmazáskódban. A mikro-optimalizálás használata előtt mindig a felhasználó szemszögéből mérje meg a referenciaértéket.
következtetés
véleményem szerint a class
lehet, hogy kényelmes szintaxisa van, de ez nem pótolhatja azt a tényt, hogy az óvatlan felhasználókat arra készteti, hogy összeomlik az osztály örökségének szikláin., Az is kockázatos, mert a jövőben érdemes lehet frissíteni, hogy egy gyárban, de a hívó lesz szorosan kapcsolódik a konstruktor függvény, mert a new
kulcsszó, valamint az a tény, hogy a mozgó órák gyárak egy törés változás.
lehet, hogy úgy gondolja,hogy csak refactor a hívás oldalak, de a nagy csapatok, vagy ha az osztály dolgozik része egy nyilvános API, meg tudná törni kódot, amely nem a kontroll. Más szavakkal, nem mindig feltételezhetjük, hogy a hívók újrakihelyezése még egy lehetőség.,
a gyárakban az a menő, hogy nem csak erősebbek és rugalmasabbak, hanem a legegyszerűbb módja annak, hogy egész csapatokat és teljes API felhasználói bázisokat ösztönözzenek egyszerű, rugalmas és biztonságos minták használatára.