Ruby's || = (lub równa się) w JavaScript?

128

Uwielbiam ||=mechanizm Ruby . Jeśli zmienna nie istnieje lub istnieje nil, utwórz ją i ustaw jako coś:

amount # is nil
amount ||= 0 # is 0
amount ||= 5 # is 0

Muszę teraz zrobić coś podobnego w JavaScript. Jaka jest konwencja lub właściwy sposób, aby to zrobić? Wiem, że ||=to nieprawidłowa składnia. 2 oczywiste sposoby radzenia sobie z tym to:

window.myLib = window.myLib || {};

// or

if (!window.myLib)
  window.myLib = {};
w.
źródło

Odpowiedzi:

152

Obie są absolutnie poprawne, ale jeśli szukasz czegoś, co działa jak ||=w rubinie. Pierwsza metoda, której variable = variable || {}szukasz :)

Dzung Nguyen
źródło
1
Ostrożnie używaj tego, jeśli prawidłowa wartość dla xjest fałszywa, na przykład false, i chcesz ustawić wartość domyślną tylko wtedy, gdy xjest niezdefiniowana.
Joshua Pinter
powyższy komentarz jest słuszny. Biorąc pod uwagę Twój przykład, w JS to nie będzie działać w ten sam sposób. let amount = 0;a następnie amount = amount || 5 zmieni liczbę na 5. Jeśli nie chcesz, aby tak się stało, użyj ??operatora zamiast ||.
AshwinKumarS
@AshwinKumarS Lub po prostu użyj amount ??= 5;.
user4642212
@ user4642212 Nie sądzę, że składnia działa w JS, prawda?
AshwinKumarS
@AshwinKumarS Tak, to prawda. Zobacz dokumentację , specyfikację , ofertę .
user4642212
22

Możesz użyć logicznego operatora OR, ||który ocenia jego prawy operand, jeśli lValjest fałszywą wartością.

Do fałszywych wartości należą np null, false, 0, "", undefined, NaN

x = x || 1
Moritz Roessler
źródło
Ostrożnie używaj tego, jeśli prawidłowa wartość dla xjest fałszywa, na przykład false, i chcesz ustawić wartość domyślną tylko wtedy, gdy xjest niezdefiniowana.
Joshua Pinter
4

Jeśli pracujesz z obiektami, możesz użyć destrukturyzacji (od ES6) w następujący sposób:

({ myLib: window.myLib = {} } = window);

... ale nie zyskujesz nic poza zaakceptowaną odpowiedzią, z wyjątkiem zamieszania.

Poczucie
źródło
1
„ale nie zyskujesz nic poza zaakceptowaną odpowiedzią poza pomyłką” - fajnie. :)
lindes
Założę się, że ktoś potraktuje to jako powód do nienawiści do javascript
Volper
1

Operator, o który pytałeś , został zaproponowany jako funkcja w JavaScript . Obecnie jest na etapie 3 , więc nie jest jeszcze oficjalną częścią języka, ale zostanie zaakceptowany, z co najwyżej niewielkimi zmianami, jeśli wykryją poważne niespodziewane problemy.

Możesz go teraz używać za pomocą wtyczki Babel plugin-offer-logical-assignment operator . Nigdy nie używałem tej wtyczki, więc nie mam pojęcia, jak dobrze to działa.

Elias Zamaria
źródło
-1

Przypisanie Rubiego || = operator zwarcia. Można to sobie wyobrazić w ten sposób:

return a || a = b

Więc w javascript wygląda to bardzo podobnie:

return a || (a = b);

Wydaje się jednak, jak wskazano w komentarzach poniżej, że ta dosłowna forma rubinowa jest mniej wydajna niż standardowy idiom javascript a = a || b.

Dla odniesienia: http://www.rubyinside.com/what-rubys-double-pipe-or-equals-really-does-5488.html

chris
źródło
1
W praktyce wydaje się, że a = a || bforma jest bardziej optymalna jsperf.com/x-or-x-equals-0-vs-x-equals-x-or-0/3
jchook
ah fajne narzędzie. jak to wygląda, jeśli x ma wartość, a więc zwarcia?
chris
Uważam, że porzucenie musi być jawne w jsperf, więc ten test powinien pokazać wydajność zwarcia. Domyślam się, że V8 ma specjalną optymalizację formy a = a || b.
jchook
3
FYI Wygląda na to, że wszelkie różnice zostały już zoptymalizowane.
Charles Wood
a || (a = b)ma poprawną semantykę do wnioskowania nazw funkcji. Obecnie trwa dyskusja nad nowym wnioskiem.
user4642212
-1

Możesz osiągnąć pożądane zachowanie za pomocą operatora | = w javascript tylko dla liczb całkowitych. Ale najpierw musisz zdefiniować zmienną.

let a = 0
a |= 100
console.log(a) // 100

Do obiektów

let o = {}
o.a |= 100
console.log(o) // {a: 100}

Dla tablic

let arr = []
arr[0] |= 100
console.log(arr) // [100]
wallgeek
źródło
Pytanie nie dotyczy |ani |=. Pożądane zachowanie w pytaniu nie jest związane z operacjami bitowymi.
user4642212
Masz rację, odpowiednio zmodyfikuję odpowiedź
wallgeek
Edytowano. Mam nadzieję, że teraz ma to sens.
wallgeek