Rozejrzałem się, jak użyć tej Object.defineProperty
metody, ale nie znalazłem nic przyzwoitego.
Ktoś dał mi ten fragment kodu :
Object.defineProperty(player, "health", {
get: function () {
return 10 + ( player.level * 15 );
}
})
Ale ja tego nie rozumiem. Głównie get
tego nie mogę dostać (zamierzona gra słów). Jak to działa?
javascript
object
defineproperty
Agregat matematyczny
źródło
źródło
Odpowiedzi:
Ponieważ zadałeś podobne pytanie , zróbmy to krok po kroku. Jest nieco dłuższy, ale może zaoszczędzić znacznie więcej czasu, niż poświęciłem na napisanie tego:
Właściwość jest funkcją OOP zaprojektowaną do czystego oddzielania kodu klienta. Na przykład w pewnym sklepie internetowym możesz mieć takie obiekty:
Następnie w kodzie klienta (e-sklepie) możesz dodać rabaty do swoich produktów:
Później właściciel e-sklepu może zdać sobie sprawę, że rabat nie może przekroczyć 80%. Teraz musisz znaleźć KAŻDY przypadek modyfikacji rabatu w kodzie klienta i dodać wiersz
Następnie właściciel e-sklepu może zmienić strategię, na przykład „jeśli klient jest sprzedawcą, maksymalna zniżka może wynosić 90%” . I musisz ponownie wprowadzić zmiany w wielu miejscach, a także pamiętać o zmianie tych linii za każdym razem, gdy zmienia się strategia. To zły projekt. Właśnie dlatego kapsułkowanie jest podstawową zasadą OOP. Jeśli konstruktor był taki:
Następnie możesz po prostu zmienić metody
getDiscount
( akcesor ) isetDiscount
( mutator ). Problem polega na tym, że większość członków zachowuje się jak wspólne zmienne, tylko zniżka wymaga tutaj szczególnej uwagi. Ale dobry projekt wymaga enkapsulacji każdego elementu danych, aby kod był rozszerzalny. Musisz więc dodać dużo kodu, który nic nie robi. Jest to również zły projekt, antipattern z płytą grzejną . Czasami nie można po prostu zmienić pól na metody później (kod eshopu może się rozrosnąć lub jakiś kod innej firmy może zależeć od starej wersji), więc podstawa jest tutaj mniejsza zła. Ale wciąż jest zły. Właśnie dlatego właściwości zostały wprowadzone w wielu językach. Możesz zachować oryginalny kod, po prostu przekształć członka rabatowego we właściwość za pomocąget
iset
bloki:Uwaga na przedostatni wiersz: odpowiedzialność za prawidłową wartość rabatu została przeniesiona z kodu klienta (definicja sklepu internetowego) do definicji produktu. Produkt jest odpowiedzialny za utrzymanie spójności swoich członków danych. Dobry projekt jest (z grubsza powiedziane), jeśli kod działa tak samo, jak nasze myśli.
Tyle o właściwościach. Ale javascript różni się od czysto obiektowych języków, takich jak C #, i koduje funkcje inaczej:
W języku C # przekształcanie pól we właściwości jest przełomową zmianą , więc pola publiczne powinny być zakodowane jako właściwości automatycznie implementowane, jeśli kod może być używany w osobno skompilowanym kliencie.
W Javascript standardowe właściwości (element danych z geterem i seterem opisanym powyżej) są zdefiniowane przez deskryptor akcesora (w linku, który masz w swoim pytaniu). Wyłącznie możesz użyć deskryptora danych (więc nie możesz użyć np. Wartości i ustawić tej samej właściwości):
Oba deskryptory mogą mieć następujących członków:
for(var i in theObject)
; jeśli false, nie będzie iterowany, ale nadal będzie dostępny jako publiczny* chyba że w trybie ścisłym - w takim przypadku JS zatrzymuje wykonywanie z TypeError, chyba że zostanie złapany w bloku try-catch
Aby odczytać te ustawienia, użyj
Object.getOwnPropertyDescriptor()
.Dowiedz się na przykładzie:
Jeśli nie chcesz zezwalać kodowi klienta na takie kody, możesz ograniczyć obiekt przez trzy poziomy ograniczenia:
Object.isExtensible(<yourObject>)
do sprawdzania, czy na obiekcie użyto metody. Zapobieganie jest płytkie (czytaj poniżej).configurable: false
wszystkie właściwości). SłużyObject.isSealed(<yourObject>)
do wykrywania tej funkcji na obiekcie. Pieczęć jest płytka (czytaj poniżej).writable: false
na wszystkie właściwości z deskryptorem danych). Nie ma to wpływu na zapisywalną właściwość Settera (ponieważ jej nie ma). Zamrożenie jest płytkie : oznacza to, że jeśli właściwość to Object, wówczas jej właściwości NIE SĄ zamrożone (jeśli chcesz, powinieneś wykonać coś w rodzaju „głębokiego zamrożenia”, podobnie jak głębokie kopiowanie - klonowanie ). Użyj,Object.isFrozen(<yourObject>)
aby go wykryć.Nie musisz się tym przejmować, jeśli piszesz tylko kilka linijek zabawy. Ale jeśli chcesz zakodować grę (jak wspomniałeś w łączonym pytaniu), powinieneś naprawdę dbać o dobry projekt. Spróbuj wyszukać w Google coś na temat antypotów i zapachu kodu . Pomoże Ci to uniknąć sytuacji takich jak „Och, muszę ponownie całkowicie przepisać mój kod!” , może zaoszczędzić miesięcy rozpaczy, jeśli chcesz dużo kodować. Powodzenia.
źródło
function Product(name,price) { this.name = name; this.price = price; var _discount; // private member Object.defineProperty(this,"discount",{ get: function() { return _discount; }, set: function(value) { _discount = value; if(_discount>80) _discount = 80; } }); } var sneakers = new Product("Sneakers",20); sneakers.discount = 50; // 50, setter is called sneakers.discount+= 20; // 70, setter is called sneakers.discount+= 20; // 80, not 90! alert(sneakers.discount); // getter is called
get
to funkcja wywoływana podczas próby odczytania wartościplayer.health
, na przykład w:W rzeczywistości niewiele różni się od:
Ustawione jest przeciwieństwo get, które będzie użyte podczas przypisywania do wartości. Ponieważ nie ma setera, wydaje się, że przypisywanie do zdrowia gracza nie jest zamierzone:
Bardzo prosty przykład:
źródło
()
wywoływać ... Nie rozumiem, jaki był pomysł, kiedy to wymyślili. Funkcje są całkowicie takie same: jsbin.com/bugipi/edit?js,console,outputZdefiniuj właściwość to metoda na Object, która pozwala skonfigurować właściwości w celu spełnienia niektórych kryteriów. Oto prosty przykład z obiektem pracownika z dwiema właściwościami FirstName i lastName i dołącz te dwie właściwości, zastępując metodę toString na obiekcie.
Otrzymasz Output jako: Jameel Moideen
Zamierzam zmienić ten sam kod, używając definicji obiektu na obiekcie
Pierwszy parametr to nazwa obiektu, a następnie drugi parametr to nazwa dodawanej właściwości, w naszym przypadku toString, a następnie ostatni parametr to obiekt json, którego wartość będzie funkcją, a trzy parametry do zapisu, zliczalne i konfigurowalne. Teraz właśnie zadeklarowałem wszystko jako prawdziwe.
Jeśli uruchomisz przykład, otrzymasz Output jako: Jameel Moideen
Rozumiemy, dlaczego potrzebujemy trzech właściwości, takich jak zapis, możliwość wyliczenia i konfigurowalność.
zapisywalny
Jedną z bardzo irytujących części javascript jest, jeśli zmienisz właściwość toString na coś innego, na przykład
jeśli uruchomisz to ponownie, wszystko się zepsuje. Zmieńmy zapisywalny na false. Jeśli uruchomisz to samo ponownie, otrzymasz poprawne wyjście jako „Jameel Moideen”. Ta właściwość zapobiegnie późniejszemu zastąpieniu tej właściwości.
wyliczalny
jeśli wydrukujesz wszystkie klucze wewnątrz obiektu, możesz zobaczyć wszystkie właściwości, w tym toString.
jeśli ustawisz element enumerable na false, możesz ukryć właściwość toString przed wszystkimi innymi. Jeśli uruchomisz to ponownie, otrzymasz FirstName, lastName
konfigurowalny
jeśli ktoś później ponownie zdefiniował obiekt później, na przykład wyliczalny na true i uruchom go. Możesz zobaczyć, że właściwość toString pojawiła się ponownie.
możesz ograniczyć to zachowanie, ustawiając konfigurowalne na false.
Oryginalne odniesienie do tych informacji pochodzi z mojego osobistego bloga
źródło
Zasadniczo
defineProperty
jest to metoda, która przyjmuje 3 parametry - obiekt, właściwość i deskryptor. W tym konkretnym wywołaniu"health"
właściwośćplayer
obiektu zostaje przypisana do 10 plus 15-krotności poziomu obiektu gracza.źródło
tak, nie ma już rozszerzania funkcji dla narzędzia ustawiającego i pobierającego to mój przykład Object.defineProperty (obj, name, func)
źródło
Object.defineProperty () jest funkcją globalną. Nie jest dostępna w funkcji, która deklaruje obiekt w inny sposób. Będziesz musiał go użyć statycznie ...
źródło
Podsumowanie:
Object.defineProperty
służy do utworzenia nowej właściwości na obiekcie gracza.Object.defineProperty
jest funkcją, która jest natywnie obecna w środowisku wykonawczym JS i przyjmuje następujące argumenty:Object.defineProperty(obj, prop, descriptor)
Obiekt deskryptora jest interesującą częścią. Tutaj możemy zdefiniować następujące rzeczy:
<boolean>
: jeślitrue
deskryptor właściwości może zostać zmieniony, a właściwość może zostać usunięta z obiektu. Jeśli konfigurowalnefalse
są przekazywane właściwości deskryptora,Object.defineProperty
nie można ich zmienić.<boolean>
: jeślitrue
właściwość może zostać zastąpiona za pomocą operatora przypisania.<boolean>
: jeślitrue
właściwość może być iterowana wfor...in
pętli. Również podczas korzystania zObject.keys
funkcji przycisk będzie obecny. Jeśli właściwość jestfalse
, nie będą iterowane przy użyciufor..in
pętli i nie będą wyświetlane podczas używaniaObject.keys
.<function>
: wymagana jest funkcja wywoływana za każdym razem, gdy właściwość jest wymagana. Zamiast podawać wartość bezpośrednią wywoływana jest ta funkcja, a zwracana wartość jest podawana jako wartość właściwości<function>
: funkcja wywoływana za każdym razem, gdy właściwość jest przypisana. Zamiast ustawiania wartości bezpośredniej wywoływana jest ta funkcja, a zwracana wartość służy do ustawiania wartości właściwości.Przykład:
źródło
źródło
Definiuje nową właściwość bezpośrednio na obiekcie lub modyfikuje istniejącą właściwość na obiekcie i zwraca obiekt.
Proste objaśnienie definicji właściwości.
Przykładowy kod: https://jsfiddle.net/manoj_antony32/pu5n61fs/
źródło
źródło