Przejście od `prototype` i` new` do wzoru zamknięcia i ekspozycji
Ponownie faktoring innego kodu JavaScript.
PRZED:
function SomeObj(flag) {
var _private = true;
this.flag = (flag) ? true : false;
this.version="1.1 (prototype)";
if (!this._someProperty) this._init();
// leading underscore hints at what should be a 'private' to me
this.reset(); // assumes reset has been added...
}
SomeObj.prototype.reset = function() {
/* perform some actions */
}
/* UPDATE */
SomeObj.prototype.getPrivate = function() {
return _private; // will return undefined
}
/* ...several other functions appended via `prototype`...*/
PO:
var SomeObj = function (flag) {
var _private = true;
this.flag = (flag) ? true : false;
this.version = "2.0 (constructor)";
this.reset = function () {
/* perform some actions */
};
/* UPDATE */
this.getPrivate = function() {
return _private; // will return true
}
/* other functions and function calls here */
}
Dla mnie pierwszy przykład jest trudny do odczytania, zwłaszcza w szerszym kontekście. Dodawanie metod takich jakreset
w ten sposób, używającprototype
właściwość wydaje się znacznie mniej kontrolowana, ponieważ może się zdarzyć w dowolnym miejscu skryptu. Mój refaktoryzowany kod (drugi przykład powyżej) wygląda dla mnie znacznie ciekawiej i dlatego jest łatwiejszy do odczytania, ponieważ jest samowystarczalny. Zdobyłem trochę prywatności dzięki deklaracjom zmiennych, ale straciłem możliwości łańcucha prototypów.
...
PYTANIA:
Po pierwsze, interesuje mnie, co jeszcze straciłem, uprzedzającprototype
lub jeśli istnieją większe implikacje dla utraty łańcucha prototypów.Ten artykuł ma 6 lat, ale twierdzi, że używaprototype
nieruchomość jest znacznie bardziej wydajna na dużą skalę niż wzory zamknięcia.
Oba powyższe przykłady nadal będą tworzone przez anew
operator; oba są „klasycznymi” konstruktorami. W końcu chciałbym nawet odejść od tego modelu, w którym wszystkie właściwości i funkcje są zadeklarowane jakovar
s i mam jedną metodę, którą ujawniam, która jest w stanie zwrócić obiekt otwierający wszystkie potrzebne mi właściwości i metody,które mają przywileje (na mocy zamknięcia) do tych, które są prywatne. Coś takiego:
var SomeObj = (function () {
/* all the stuff mentioned above, declared as 'private' `var`s */
/* UPDATE */
var getPrivate = function () {
return private;
}
var expose = function (flag) {
// just returns `flag` for now
// but could expose other properties
return {
flag: flag || false, // flag from argument, or default value
getPrivate: getPrivate
}
};
return {
expose: expose
}
})(); // IIFE
// instead of having to write `var whatever = new SomeObj(true);` use...
var whatever = SomeObj.expose();
Na StackOverflow znajduje się kilka odpowiedzi dotyczących pytania „prototyp vs. zamknięcie” (tutaj itutaj, na przykład). Ale tak jak w przypadkuprototype
Właściwość, interesuje mnie, co za ruch w tym kierunku iz dala odnew
operator oznacza wydajność mojego kodu i wszelką utratę możliwości (np.instanceof
zgubiony). Jeśli i tak nie zamierzam korzystać z dziedziczenia prototypowego, czy faktycznie tracę cokolwiek z powyższegonew
operator?
Luźniejsze pytanie, czy mogę to zrobić, biorąc pod uwagę, że pytam o szczegóły powyżej: jeśliprototype
inew
naprawdę jest to najbardziej skuteczny sposób, z większą przewagą (niezależnie od tego, co uważasz za możliwe) niż zamknięcie, czy są jakieś wytyczne lub wzorce projektowe do pisania w schludniejszy sposób?
...
AKTUALIZACJA:Zauważ, żeexpose
za każdym razem zwraca nowy obiekt, więc dzieje się w tym miejscu. Jak rozumiem, gdzie ten obiekt odnosi się do metod zadeklarowanych wSomeObj
są to te same metody we wszystkich obiektach (chyba że zostaną nadpisane). W przypadkuflag
zmienna (którą teraz poprawiłem), można ją odziedziczyć po argumencieexpose
, mają wartość domyślną lub ponownie odwołują się do zamkniętej wcześniej istniejącej metody lub właściwości. Istnieją więc przypadki tworzenia obiektów i dzieje się tutaj pewne dziedziczenie (plus polimorfizm?).
Tak więc powtórz pytanie 2: Jeśli i tak nie zamierzam korzystać z dziedziczenia prototypowego, to czy rzeczywiście stracę cokolwiek z powyższegonew
operator?
Bardzo dziękuję za dotychczasowe odpowiedzi, które pomogły wyjaśnić moje pytanie.