Operatory trójskładnikowe w JavaScript bez „innego”


149

Zawsze musiałem stawiać nullna inne warunki, które nic nie mają. Czy jest coś dookoła? Na przykład

condition ? x = true : null;

w zasadzie, czy jest na to sposób:

condition ? x = true;

Teraz pojawia się jako błąd składni

FYI, oto prawdziwy przykładowy kod:

!defaults.slideshowWidth ? defaults.slideshowWidth = obj.find('img').width()+'px' : null;

21
użycie trójskładnika podobnego condition ? x = true : null;powinno być prawdopodobnie zapisane jako x = (condition ? true : null);. Nawiasem mówiąc, w javascript nullocenia się na false, więc w TYM przypadku możesz x = (condition);i osiągnąć ten sam wynik.
Matt S

1
Matt, twoja odpowiedź jest najlepsza, ale to nie jest odpowiedź, to komentarz!
Cheeso

Matt, mój RZECZYWISTY kod to:! Defaults.slideshowWidth? defaults.slideshowWidth = obj.find ('img'). width () + 'px': null; krótszy, lepszy sposób, żeby to napisać?
Oscar Godson

2
defaults.slideshowWidth = defaults.slideshowWidth || obj.find ('img'). width () + 'px';
kennebec

lepiej byłoby uniknąć przypisywania tożsamości, więc powinien to być tylko warunek:if (!defaults.slideshowWidth) defaults.slideshowWidth = obj.find('img').width()+'px'
Mihail Malostanidis

Odpowiedzi:


226

Po pierwsze, wyrażenie trójskładnikowe nie jest zamiennikiem konstrukcji if / else - jest odpowiednikiem konstrukcji if / else, która zwraca wartość. Oznacza to, że klauzula if / else jest kodem, a wyrażenie trójskładnikowe jest wyrażeniem , co oznacza, że ​​zwraca wartość.

Oznacza to kilka rzeczy:

  • Używaj wyrażeń trójskładnikowych tylko wtedy, gdy po lewej stronie zmiennej, =której ma zostać przypisana wartość zwracana, znajduje się zmienna
  • używaj wyrażeń trójskładnikowych tylko wtedy, gdy zwracana wartość ma być jedną z dwóch wartości (lub użyj wyrażeń zagnieżdżonych, jeśli pasuje)
  • każda część wyrażenia (po? i after:) powinna zwracać wartość bez skutków ubocznych (wyrażenie x = truezwraca prawdę, ponieważ wszystkie wyrażenia zwracają ostatnią wartość, ale także zmienia x bez x, które mają wpływ na zwracaną wartość)

Krótko mówiąc - „prawidłowe” użycie wyrażenia trójskładnikowego to

var resultofexpression = conditionasboolean ? truepart: falsepart;

Zamiast przykładu condition ? x=true : null ;, w którym używasz wyrażenia trójskładnikowego do ustawienia wartości x, możesz użyć tego:

 condition && (x = true);

Jest to nadal wyrażenie i dlatego może nie przejść walidacji, więc byłoby jeszcze lepsze podejście

 void(condition && x = true);

Ostatni przejdzie walidację.

Ale z drugiej strony, jeśli oczekiwana wartość jest wartością logiczną, po prostu użyj wyniku samego wyrażenia warunku

var x = (condition); // var x = (foo == "bar");

AKTUALIZACJA W odniesieniu do twojej próbki jest to prawdopodobnie bardziej odpowiednie:

defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width()+'px';

4
genialny SO, nie pozwalający na edycję, aby poprawić i/elseliterówkę, ponieważ nie ma wystarczającej liczby znaków.
dewd

1
void (condition && x = true) - wygląda świetnie, ale wydaje się powodować błąd „nieprawidłowe przypisanie po lewej stronie”
Eugene Tiurin

1
void (condition && (x = true)) // oddziela przypisanie od pierwszej wartości
diamondsea

4
Jednak nie jest to intuicyjne czytanie, szczególnie dla programistów, którzy nie są przyzwyczajeni do tego stylu. Możesz równie łatwo i czytelniej napisać to jako: if (warunek) {x = prawda; }
diamondsea

2
Czy mógłbyś wyjaśnić, co masz na myśli, mówiąc „może nie przejść walidacji”? Nie rozumiem, dlaczego należy zawrzeć to wyrażenie void(). dzięki.
gilad mayani

20

Nie, potrzebuje trzech operandów. Dlatego nazywane są operatorami trójskładnikowymi .

Jednak dla tego, co masz jako przykład, możesz zrobić to:

if(condition) x = true;

Chociaż bezpieczniej jest mieć nawiasy klamrowe, jeśli chcesz dodać więcej niż jedną instrukcję w przyszłości:

if(condition) { x = true; }

Edycja: Teraz, gdy podasz rzeczywisty kod, którego dotyczy Twoje pytanie:

if(!defaults.slideshowWidth)
    { defaults.slideshowWidth = obj.find('img').width()+'px'; }

1
Możesz, ale nie powinieneś. Przynajmniej nie bez nawiasów klamrowych wokół niego - jest to bardzo podatne na błędy.
Konerak

1
czy to prawda? Zrozumiałem, że głównym powodem wymagania curlies jest to, że ułatwiają życie jslint.
Cheeso

@Cheeso jest podatne na błędy w sensie refaktoryzacji. Wrócisz, aby dodać więcej do zrobienia w przypadku prawdziwego stanu, nie zdając sobie sprawy, że nie ma tam aparatu ortodontycznego. Nowy kod będzie zawsze wykonywany, a nie gdy prawda.
Matt S

Nie, wiem, po prostu lubię pisać warunki warunkowe bez dodatków, takich jak if () {} else {}, gdy jest równe po prostu?:;
Oscar Godson

3
Szczerze mówiąc, nigdy nie spotkałem programistów bardziej obawiających się używania języka niż Javascript: - Nie chciałbym, żeby ktoś mi powiedział, że nie powinienem używać nawiasów klamrowych. Bardzo je pomijam i nigdy nie mam więcej kłopotów, niż przypadkowo przegapiłbym aparat.
Andy E

12

Coraz częściej ludzie używają operatorów logicznych, aby skrócić składnię instrukcji:

!defaults.slideshowWidth &&
  (defaults.slideshowWidth = obj.find('img').width()+'px');

Ale w twoim konkretnym przypadku składnia może być jeszcze prostsza

defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width()+'px';

Ten kod zwróci defaults.slideshowWidthwartość, jeśli defaults.slideshowWidthzostanie oszacowana jako true iobj.find('img').width()+'px' wartość w przeciwnym razie.

Aby uzyskać szczegółowe informacje, patrz Ocena zwarć operatorów logicznych.


11
var x = condition || null;

2
(defaults.slideshowWidth) || (defaults.slideshowWidth = obj.find('img').width()+'px')lubdefaults.slideshowWidth = defaults.slideshowWidth || (obj.find('img').width()+'px')
Casey Chu

> Zwraca wyrażenie1, jeśli można je przekonwertować na wartość true; w przeciwnym razie zwraca wyrażenie2. Operatory logiczne (MDN)
Szabolcs Páll

5

Możesz pisać

x = condition ? true : x;

Tak więc x jest niezmodyfikowane, gdy warunek jest fałszywy.

To jest równoważne z

if (condition) x = true

EDYTOWAĆ:

!defaults.slideshowWidth 
      ? defaults.slideshowWidth = obj.find('img').width()+'px' 
      : null 

Jest kilka alternatyw - nie mówię, że są lepsze / gorsze - są to tylko alternatywy

Przekazywanie wartości null jako trzeciego parametru działa, ponieważ istniejąca wartość ma wartość null. Jeśli dokonasz refaktoryzacji i zmienisz warunek, istnieje niebezpieczeństwo, że nie jest to już prawdą. Przekazywanie istniejącej wartości jako drugi wybór w trójskładnikowej ochronie przed tym:

!defaults.slideshowWidth = 
      ? defaults.slideshowWidth = obj.find('img').width()+'px' 
      : defaults.slideshowwidth 

Bezpieczniejsze, ale może nie tak przyjemne dla oka i więcej pisania. W praktyce pewnie bym napisał

defaults.slideshowWidth = defaults.slideshowWidth 
               || obj.find('img').width()+'px'

Jakiś kod na żywo to (tak czy inaczej, aby pozbyć się w tym null?):! Defaults.slideshowWidth? defaults.slideshowWidth = obj.find ('img'). width () + 'px': null;
Oscar Godson

2

W twoim przypadku widzę operator trójskładnikowy jako zbędny. Możesz przypisać zmienną bezpośrednio do wyrażenia, używając operatorów ||, &&.

!defaults.slideshowWidth ? defaults.slideshowWidth = obj.find('img').width()+'px' : null ;

stanie się :

defaults.slideshowWidth = defaults.slideshowWidth || obj.find('img').width()+'px';

Jest bardziej przejrzysty, bardziej w stylu „javascript”.



1

Aby użyć operatora trójargumentowego bez innego elementu wewnątrz tablicy lub deklaracji obiektu, można użyć operatora rozproszenia ES6 ...()

const cond = false;
const arr = [
  ...(cond ? ['a'] : []),
  'b',
];
    // ['b']

A dla obiektów:

const cond = false;
const obj = {
  ...(cond ? {a: 1} : {}),
  b: 2,
};
    // {b: 2}

Pierwotnym źródłem

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.