Czy jest jakiś sposób, aby uzyskać coś takiego do pracy w JavaScript?
var foo = {
a: 5,
b: 6,
c: this.a + this.b // Doesn't work
};
W obecnej formie ten kod generuje błąd referencyjny, ponieważ this
nie odnosi się do foo
. Ale czy jest jakiś sposób, aby wartości we właściwościach literału obiektu zależały od innych właściwości zadeklarowanych wcześniej?
javascript
object-literal
kpozin
źródło
źródło
foo.a
lubfoo.b
zostaną zmienione, wówczas wartość zmiennejfoo.c
również zmieni się synchronicznie. To może być lub nie być wymagane.this
wiąże się z najgłębiej zagnieżdżonym obiektem. Np .:... x: { get c () { /*this is x, not foo*/ } } ...
foo
jest deklarowane jako zmienna ic
będzie oceniane tylko w momencie jego wywołania, użyciefoo
wewnątrzc
będzie działać, w przeciwieństwie dothis
(bądź ostrożny)Możesz zrobić coś takiego:
Byłaby to pewnego rodzaju jednorazowa inicjalizacja obiektu.
Zauważ, że faktycznie przypisujesz wartość zwracaną
init()
dofoo
, dlatego musiszreturn this
.źródło
delete this.init
wcześniej,return this
abyfoo
nie było zanieczyszczoneinit()
wywołanie zostało bezpośrednio dołączone do literału, aby zachować jedno wyrażenie. Ale oczywiście możesz wywołać tę funkcję oddzielnie od siebie.Brakuje oczywistej, prostej odpowiedzi, więc dla kompletności:
Nie. Wszystkie rozwiązania tutaj odraczają go do momentu utworzenia obiektu (na różne sposoby), a następnie przypisują trzecią właściwość. Najprostszym sposobem jest po prostu to zrobić:
Wszystkie inne są po prostu bardziej pośrednimi sposobami na zrobienie tego samego. (Felix's jest szczególnie sprytny, ale wymaga utworzenia i zniszczenia funkcji tymczasowej, zwiększenia złożoności; albo pozostawia dodatkową właściwość na obiekcie, albo [jeśli
delete
ta właściwość] wpływa na wydajność dostępu do kolejnych właściwości na tym obiekcie).Jeśli potrzebujesz, aby wszystkie znajdowały się w jednym wyrażeniu, możesz to zrobić bez właściwości tymczasowej:
Lub oczywiście, jeśli musisz to zrobić więcej niż raz:
następnie, gdzie musisz go użyć:
źródło
this
jest dostępny tylko dla metod tego obiektu, a nie innych rodzajów właściwości. Masz pomysł, gdzie mogę to znaleźć? Dzięki!delete
jest o 10% szybsza, a gekon:delete
tylko o 1% wolniejsza.Po prostu utwórz instancję anonimowej funkcji:
źródło
new Point(x, y)
z wyjątkiem tego, że funkcja nie jest nazwana do ponownego użycia.var foo = function() { this.…; return this; }.call({});
który nie różni się składniowo, ale semantycznie rozsądny.new
słowa kluczowego.Teraz w ES6 możesz tworzyć leniwe właściwości buforowane. Przy pierwszym użyciu właściwość ocenia raz, aby stać się normalną właściwością statyczną. Wynik: za drugim razem pomijany jest narzut funkcji matematycznych.
Magia jest w getterze.
W pobocznym strzale
this
pobiera otaczający zakres leksykalny .źródło
Object.defineProperty(foo, 'c', {get:function() {...}})
je zdefiniować. Można to łatwo zrobić w dyskretny sposób w fabryce takiej jak ta. Oczywiście, jeśli możesz użyćget
cukru, jest on bardziej czytelny, ale istnieje możliwość.Niektóre zamknięcie powinno sobie z tym poradzić;
Wszystkie zmienne zadeklarowane wewnątrz
foo
są prywatnefoo
, jak można się spodziewać w przypadku każdej deklaracji funkcji, a ponieważ wszystkie są w zakresie, wszystkie mają dostęp do siebie bez potrzeby odwoływania sięthis
, tak jak można by się spodziewać po funkcji. Różnica polega na tym, że ta funkcja zwraca obiekt, który ujawnia zmienne prywatne i przypisuje ten obiekt dofoo
. Na koniec zwracasz tylko interfejs, który chcesz udostępnić jako obiekt zreturn {}
instrukcją.Funkcja jest następnie wykonywana na końcu,
()
co powoduje, że cały obiekt foo jest oceniany, wszystkie zmienne w instancji i zwracany obiekt są dodawane jako właściwościfoo()
.źródło
Możesz to zrobić w ten sposób
Ta metoda okazała się przydatna, gdy musiałem odwoływać się do obiektu, na którym pierwotnie zadeklarowano funkcję. Poniżej znajduje się minimalny przykład tego, jak go użyłem:
Definiując self jako obiekt zawierający funkcję drukowania, pozwalasz funkcji odwoływać się do tego obiektu. Oznacza to, że nie musisz „wiązać” funkcji drukowania z obiektem, jeśli musisz przekazać go gdzie indziej.
Jeśli wolisz, użyj tego,
this
jak pokazano poniżejNastępnie poniższy kod zarejestruje 0, 1, 2, a następnie wyświetli błąd
Korzystając z metody self, gwarantujesz, że druk zawsze zwróci ten sam obiekt, niezależnie od kontekstu, w którym funkcja jest uruchomiona. Powyższy kod będzie działał dobrze i logował się 0, 1, 2 i 3, gdy używasz własnej wersji
createMyObject()
.źródło
Na zakończenie w ES6 mamy klasy (obsługiwane w momencie pisania tego tylko w najnowszych przeglądarkach, ale dostępne w Babel, TypeScript i innych transpilerach)
źródło
Możesz to zrobić przy użyciu wzorca modułu. Tak jak:
Za pomocą tego wzorca można utworzyć kilka obiektów Foo zgodnie z potrzebami.
http://jsfiddle.net/jPNxY/1/
źródło
}();
byłby, sam wykonałby i zwrócił obiekt, a nie funkcję. Ponadto,foo.c
jest to funkcja, więc pisanie na to clobbers tej funkcji i następnego wywołania poprzezfooObject.c()
zawiedzie. Być może to skrzypce jest bliższe temu, do czego dążysz (jest to także singleton, nieprzeznaczony do tworzenia instancji).Istnieje kilka sposobów na osiągnięcie tego; właśnie tego użyłbym:
źródło
tylko ze względu na przemyślenie - umieść właściwości obiektu poza osią czasu:
są też lepsze odpowiedzi powyżej . W ten sposób zmodyfikowałem przykładowy kod, który przesłuchałeś.
AKTUALIZACJA:
źródło
var foo = { get a(){return 5}, get b(){return 6}, get c(){return this.a + this.b} }
teraz możesz to zrobićfoo.c
zamiastfoo.c()
:) (Możesz wkleić to w swojej odpowiedzi, aby formatowanie było lepsze!)Tworzenie nowej funkcji dosłownie na obiekcie i wywoływanie konstruktora wydaje się radykalnym odejściem od pierwotnego problemu i jest niepotrzebne.
Nie można odwoływać się do właściwości rodzeństwa podczas inicjalizacji dosłowności obiektu.
Oto najprostsze rozwiązanie dla obliczonych właściwości (bez stosu, bez funkcji, bez konstruktora):
źródło
Inne zamieszczone tutaj odpowiedzi są lepsze, ale oto alternatywa:
init()
ani kodu poza literałem obiektuSamoczynne anonimowe funkcje i pamięć okien
Zamówienie jest gwarantowane (
bar
wcześniejbaz
).To
window
oczywiście zanieczyszcza , ale nie wyobrażam sobie, żeby ktoś pisał scenariusz wymagającywindow.temp
wytrwałości. MożetempMyApp
jeśli jesteś paranoikiem.Jest to również brzydkie, ale czasami przydatne. Przykładem jest użycie interfejsu API ze sztywnymi warunkami inicjalizacji i nie masz ochoty na refaktoryzację, więc zakres jest poprawny.
I oczywiście jest sucho.
źródło
Kluczem do tego wszystkiego jest ZAKRES .
Musisz obudować „obiekt nadrzędny” (obiekt nadrzędny) właściwości, którą chcesz zdefiniować jako własny obiekt instancji, a następnie możesz odwoływać się do właściwości rodzeństwa za pomocą słowa kluczowego
this
Bardzo, bardzo ważne jest, aby pamiętać, że jeśli odwołujesz się do tego
this
bez uprzedniego, tothis
odniesiesz się do zewnętrznego zakresu ... który będziewindow
obiektem.źródło
jeśli twój obiekt jest zapisany jako funkcja, która zwraca obiekt, ORAZ używasz „metod” atrybut-obiektu ES6, możliwe jest:
źródło
Używam następującego kodu jako alternatywy i działa. Zmienna może być również tablicą. (@ Fausto R.)
źródło
Oto schludny sposób ES6:
Używam go do robienia czegoś takiego:
źródło
Co powiesz na to rozwiązanie, które będzie działać również z zagnieżdżonymi obiektami z tablicą
źródło
Wrzucam opcję, ponieważ nie widziałem dokładnie tego scenariusza. Jeśli nie chcesz
c
aktualizowaća
anib
aktualizować, ES6 IIFE działa dobrze.Na moje potrzeby mam obiekt, który odnosi się do tablicy, która ostatecznie zostanie użyta w pętli, więc chcę tylko raz obliczyć niektóre typowe ustawienia, więc mam to:
Ponieważ muszę ustawić właściwość
indexOfSelectedTier
i muszę użyć tej wartości podczas ustawianiahasUpperTierSelection
właściwości, najpierw obliczam tę wartość i przekazuję ją jako parametr do IIFEźródło
Innym podejściem byłoby zadeklarowanie obiektu przed przypisaniem do niego właściwości:
Dzięki temu możesz użyć nazwy zmiennej obiektowej, aby uzyskać dostęp do już przypisanych wartości.
Najlepsze do
config.js
pliku.źródło
foo
która wskazuje na przedmiotowy obiekt.Jest to prawie identyczne z odpowiedzią @ slicedtoad, ale nie używa funkcji.
źródło
Tutaj używaliśmy wyrażeń klas, aby uzyskać interfejs dosłowny zagnieżdżony obiekt, który chcielibyśmy. Jest to kolejna najlepsza rzecz IMHO, aby móc odwoływać się do właściwości obiektu podczas tworzenia.
Najważniejszą rzeczą do odnotowania jest to, że podczas korzystania z tego rozwiązania masz dokładnie taki sam interfejs, jak w przypadku literału obiektu. A składnia jest bardzo zbliżona do samego dosłowności obiektu (vs przy użyciu funkcji itp.).
Porównaj następujące
Rozwiązanie, które zaproponowałem
Rozwiązanie, jeśli dosłowne byłyby literały obiektowe
Inny przykład
Tutaj, w tej klasie, możesz łączyć ze sobą wiele ścieżek względnych, co nie jest możliwe w przypadku literału obiektu.
źródło
Jeśli chcesz korzystać z natywnego JS, inne odpowiedzi dostarczają dobrych rozwiązań.
Ale jeśli chcesz pisać obiekty z odnośnikami, takie jak:
Napisałem bibliotekę npm o nazwie self-referenced-object, która obsługuje tę składnię i zwraca obiekt macierzysty.
źródło
b
wartości nieruchomości powinny być:${this.a + this.a}
. Po drugie, ale mniej ważne, chciałbyś zwrócić liczbę, a nie ciąg znaków, używając czegoś takiegoparseInt
. Co najważniejsze, kiedy spróbowałem tego przykładu, po prostu nie działa, z tego samego powodu, o który prosi OP. Tethis
powroty niezdefiniowany stosowany własną deklarację obiektu. @ alex-e-leon