Pytanie Co oznacza konstrukcja x = x || y znaczy?


Mam debugowanie niektórych JavaScript i nie mogę tego wyjaśnić || robi?

function (title, msg) {
  var title = title || 'Error';
  var msg   = msg || 'Error on Request';
}

Czy ktoś może mi podpowiedzieć, dlaczego ten facet używa? var title = title || 'ERROR'? Czasami widzę to bez var również deklaracja.


163
2018-05-10 10:58


pochodzenie


Ludzie już odpowiedzieli na to ... ale zdają sobie sprawę z tego, że druga wartość jest wybrana, jeśli pierwsza wartość jest falsy, nie tylko undefined. Ile razy widziałem doWeDoIt = doWeDoIt || truewystarczy, aby mnie rozpłakać. (to znaczy doWeDoIt nigdy nie będzie false) - Matt
Zobacz też Co oznacza "opcje = opcje || {} "Oznacza w JavaScript? - Bergi
Dla osób mających doświadczenie z C #, operator dwururowy jest równoważny operatorowi łączącemu zero ??. JavaScript ocenia nie-puste obiekty lubić  true (lub lepiej evalualtes zero obiektów do false) - usr-local-ΕΨΗΕΛΩΝ
To prosty sposób na przypisanie wartości domyślnej w jednym wierszu. jak przy przypisywaniu wartości warunkowej takiej jak ta: int y = x > 2 ? x : 1 lub Object o = person ?: new Person(). - IgniteCoders
Nie czuj się źle - JS jest jedynym głupim językiem pozwalającym na takie okropne kodowanie ... i uczenie, że właściwe jest zagnieżdżać każdą funkcję w linie kodu i wyrzucać je, czyniąc je jednorazowymi i bezużytecznymi po raz drugi. :) Mam 30 lat do kodowania i wstrzymałem się z dotykaniem JS, aż do niedawna ja i czuję twój ból, wszystko, co mogę powiedzieć, to, trzymaj "nie ma sensu, to tylko w JS". ve zdobyty przez! :) - Collin Chaffin


Odpowiedzi:


Oznacza to title Argument jest opcjonalny. Więc jeśli wywołasz metodę bez argumentów, użyje ona domyślnej wartości "Error".

Skróty do napisania:

if (!title) {
  title = "Error";
}

Ten rodzaj skrótowej sztuczki z wyrażeń boolowskich jest również powszechny w Perlu. Z wyrażeniem:

a OR b

ocenia to true jeśli tak a lub b jest true. Więc jeśli a to prawda, nie musisz sprawdzać b w ogóle. Nazywa się to boolowską analizą zwarciową, więc:

var title = title || "Error";

zasadniczo sprawdza, czy title ocenia na false. Jeśli tak, to "zwraca" "Error", w przeciwnym razie powraca title.


159
2018-05-10 11:00



Przepraszam za wybredność, ale argument nie jest opcjonalny, argument jest sprawdzany - themightybun
To NIE jest odpowiedź i zgadzam się z ostatnim komentarzem, że nie jest ona nawet opcjonalna. Żadna część tej odpowiedzi nie jest poprawna nawet w odniesieniu do Perla, ponieważ instrukcja Perl faktycznie tworzy SENSE i jest oceniana w zupełnie inny sposób. JS jest eval w znacznie bardziej "skonwertowanej" metodzie logiki boolowskiej, którą ja także uważam za dużo bardziej mylącą dla odczytu / zapisu. Poniższa odpowiedź zatytułowana "Co to jest operator podwójnej rury" jest właściwie poprawną odpowiedzią. - Collin Chaffin


Co to jest operator podwójnej rury (||)?

Operator podwójnej rury (||) jest logiczny OR operator . W większość języków działa w następujący sposób:

  • Jeśli pierwsza wartość jest false, sprawdza drugą wartość. Jeśli to jest true, zwraca true a jeśli tak false, zwraca false.
  • Jeśli pierwsza wartość jest true, zawsze powraca true, bez względu na drugą wartość.

Więc w zasadzie działa tak jak ta funkcja:

function or(x, y) {
  if (x) {
    return true;
  } else if (y) {
    return true;
  } else {
    return false;
  }
}

Jeśli nadal nie rozumiesz, spójrz na tę tabelę:

      | true   false  
------+---------------
true  | true   true   
false | true   false  

Innymi słowy, jest to fałsz tylko wtedy, gdy obie wartości są fałszywe.

Czym różni się JavaScript?

JavaScript jest nieco inny, ponieważ jest luźno napisany język. W tym przypadku oznacza to, że możesz go użyć || operator z wartościami, które nie są wartościami boolowymi. Chociaż nie ma sensu, możesz użyć tego operatora, na przykład dla funkcji i obiektu:

(function(){}) || {}

Co tu się dzieje?

Jeśli wartości nie są boolowskie, JavaScript czyni niejawna konwersja do boolean. Oznacza to, że jeśli wartością jest falsey (np. 0, "", null, undefined (Zobacz też Wszystkie wartości falsey w JavaScript)), będzie traktowany jako false; w przeciwnym razie jest traktowane jako true.

Tak więc powyższy przykład powinien dać true, ponieważ pusta funkcja jest prawdą. Cóż, tak nie jest. Zwraca pustą funkcję. To dlatego, że JavaScript || operator nie działa tak jak napisałem na początku. Działa on w następujący sposób:

  • Jeśli pierwsza wartość jest falsey, zwraca druga wartość.
  • Jeśli pierwsza wartość jest prawda, zwraca pierwsza wartość.

Zaskoczony? W rzeczywistości jest "zgodny" z tradycyjnym || operator. Można go zapisać jako następującą funkcję:

function or(x, y) {
  if (x) {
    return x;
  } else {
    return y;
  }
}

Jeśli podasz wartość prawdy jako x, zwraca xto jest wartość prawdy. Więc jeśli użyjesz go później if klauzula:

(function(x, y) {
  var eitherXorY = x || y;
  if (eitherXorY) {
    console.log("Either x or y is truthy.");
  } else {
    console.log("Neither x nor y is truthy");
  }
}(true/*, undefined*/));

dostajesz "Either x or y is truthy.".

Gdyby x był falsey, eitherXorY byłoby y. W takim przypadku dostaniesz "Either x or y is truthy." gdyby y był prawdą; w przeciwnym razie dostaniesz "Neither x nor y is truthy".

Rzeczywiste pytanie

Teraz, kiedy wiesz jak || operator działa, prawdopodobnie możesz samemu się przekonać, co robi x = x || y oznaczać. Gdyby xjest prawdą, x jest przypisany do x, więc właściwie nic się nie dzieje; Inaczej y jest przypisany do x. Jest powszechnie używany do definiowania parametrów domyślnych w funkcjach. Jednak jest często uważany za zła praktyka programowania, ponieważ uniemożliwia ci podanie wartości falsey (co niekoniecznie jest konieczne) undefined lub null) jako parametr. Rozważmy następujący przykład:

function badFunction(/* boolean */flagA) {
  flagA = flagA || true;
  console.log("flagA is set to " + (flagA ? "true" : "false"));
}

Wygląda na pierwszy rzut oka. Jednak co by się stało, gdybyś zdał false tak jak flagA parametr (ponieważ jest to boolean, tj. może być true lub false)? Stałoby się true. W tym przykładzie nie ma możliwości ustawienia flagA do false.

Lepszym rozwiązaniem byłoby jednoznaczne sprawdzenie, czy flagA jest undefined, tak:

function goodFunction(/* boolean */flagA) {
  flagA = typeof flagA !== "undefined" ? flagA : true;
  console.log("flagA is set to " + (flagA ? "true" : "false"));
}

Choć jest dłuższy, zawsze działa i jest łatwiejszy do zrozumienia.


Możesz także użyć składnia ES6 dla domyślnych parametrów funkcji, ale zauważ, że nie działa w starszych przeglądarkach (np. IE). Jeśli chcesz wspierać te przeglądarki, powinieneś zaimportować swój kod Babel.

Zobacz też Operatory logiczne na MDN.


109
2018-01-10 16:18



+1 - zdecydowanie najbardziej poprawna i kompletna odpowiedź. A dla tych, którzy mają to pytanie (niektórzy z nas, weterani koderów, którzy są nowi w JS) powinni zdecydowanie skupić się na całej tej odpowiedzi na ten temat: "Choć to nie ma sensu", ponieważ ten "zapisany w loosley" po prostu nigdy nie będzie miał sensu dla tych z nas, którzy dorastali bez niego. Dla nas operator boolowski jest właśnie tym i TYLKO ...... i ktokolwiek by pomyślał, że byłoby dobrym pomysłem, aby zatrzymać i przemyśleć jakąś zwariowaną konwersję wartości nie-boolowskich na boolowskie podczas czytania / pisania kodu , zapomniałem wziąć ich meds tego dnia! :) - Collin Chaffin


Jeśli tytuł nie jest ustawiony, użyj "ERROR" jako wartości domyślnej.

Bardziej ogólny:

var foobar = foo || default;

Czyta: Ustaw foobar na foo lub default. Możesz nawet powiązać to wiele razy:

var foobar = foo || bar || something || 42;

23
2018-05-10 10:59



Stwierdziłem, że jest to mylące, ponieważ zmienne mają tę samą nazwę. O wiele łatwiej, kiedy tego nie robią. - Norbert Norbertson


Wyjaśnianie tego trochę więcej ...

The || operator jest logicznyor operator. Wynik jest prawdziwy, jeśli pierwsza część jest prawdziwa i jest prawdą, jeśli druga część jest prawdziwa i jest prawdą, jeśli obie części są prawdziwe. Dla jasności, tutaj jest w tabeli:

 X | Y | X || Y 
---+---+--------
 F | F |   F    
---+---+--------
 F | T |   T    
---+---+--------
 T | F |   T    
---+---+--------
 T | T |   T    
---+---+--------

Teraz zauważ coś tutaj? Gdyby X jest prawdą, wynik jest zawsze prawdziwy. Więc jeśli to wiemy X to prawda, że ​​nie musimy sprawdzać Y w ogóle. W związku z tym wiele języków wdraża ewaluatory "zwarć" w celuor (i logiczne-and jadąc z drugiego kierunku). Sprawdzają pierwszy element i jeśli to prawda, nie przejmują się sprawdzaniem drugiego. Wynik (w kategoriach logicznych) jest taki sam, ale pod względem wykonania istnieje potencjalnie ogromna różnica, jeśli drugi element jest drogi do wyliczenia.

Co to ma wspólnego z twoim przykładem?

var title   = title || 'Error';

Spójrzmy na to. The title element jest przekazywany do twojej funkcji. W JavaScript, jeśli nie przekazujesz parametru, domyślnie jest to wartość pusta. Również w JavaScript, jeśli twoja zmienna jest wartością pustą, jest uważana za fałszywą przez operatorów logicznych. Więc jeśli ta funkcja jest wywoływana z podanym tytułem, jest to wartość inna niż fałszywa, a zatem przypisana do zmiennej lokalnej. Jeśli jednak nie zostanie podana wartość, jest to wartość pusta, a zatem fałsz. Logiczneor operator następnie ocenia drugie wyrażenie i zwraca zamiast niego "Błąd". Teraz zmienna lokalna otrzymuje wartość "Błąd".

Działa to z powodu implementacji wyrażeń logicznych w JavaScript. Nie zwraca poprawnej wartości boolowskiej (true lub false), ale zamiast tego zwraca wartość podaną w ramach niektórych reguł, co do tego, co jest uważane za równoważne true i co uważane jest za równoważne false. Sprawdź swoje referencje JavaScript, aby dowiedzieć się, co JavaScript uważa za prawdziwe lub fałszywe w kontekście boolowskim.


13
2018-05-10 11:14





Podwójna rura oznacza logiczne "OR". Tak naprawdę nie jest, gdy "parametr nie ustawiony", ponieważ ściśle w javascript, jeśli masz kod jak poniżej:

function foo(par) {
}

Następnie połączenia

foo()
foo("")
foo(null)
foo(undefined)
foo(0)

nie są równoważne.

Podwójna rura (||) rzuci pierwszy argument na wartość logiczną, a jeśli wynikowa wartość logiczna będzie prawdziwa - wykonaj przypisanie, w przeciwnym razie przypisze odpowiednią część.

Ma to znaczenie, jeśli zaznaczysz parametr nieustawiony.

Załóżmy, że mamy funkcję setSalary, która ma jeden opcjonalny parametr. Jeśli użytkownik nie poda parametru, należy użyć wartości domyślnej 10.

jeśli wykonasz kontrolę w następujący sposób:

function setSalary(dollars) {
    salary = dollars || 10
}

To da nieoczekiwany wynik w rodzaju połączenia

setSalary(0) 

Nadal będzie ustawiać 10 po przepływie opisanym powyżej.


7
2018-05-10 11:11





Zasadniczo sprawdza, czy wartość przed || zwraca wartość true, jeśli tak, przyjmuje tę wartość, jeśli nie, przyjmuje wartość po ||.

Wartości, dla których przyjmie wartość po || (o ile pamiętam):

  • niezdefiniowany
  • fałszywy
  • 0
  • '' (Łańcuch zerowy lub zerowy)

6
2018-05-10 11:02



false || null || niezdefiniowany || 0 || '' || "zapomniałeś null" - Dziamid


podwójny operator rur

czy ten przykład jest użyteczny?

var section = document.getElementById('special');
if(!section){
     section = document.getElementById('main');
}

może też być

var section = document.getElementById('special') || document.getElementById('main');

3
2018-05-10 11:01