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.