JavaScript ИЛИ (||) объяснение назначения переменной - PullRequest
318 голосов
/ 20 января 2010

Учитывая этот фрагмент JavaScript ...

var a;
var b = null;
var c = undefined;
var d = 4;
var e = 'five';

var f = a || b || c || d || e;

alert(f); // 4

Может кто-нибудь объяснить мне, как называется эта техника (мое лучшее предположение в названии этого вопроса!)? И как / почему это работает точно?

Насколько я понимаю, переменной f будет присвоено ближайшее значение (слева направо) первой переменной, значение которой не равно ни null, ни undefined, но мне не удалось найти много ссылок материал об этой технике и видел его много.

Кроме того, эта техника специфична для JavaScript? Я знаю, что выполнение чего-то подобного в PHP приведет к тому, что f будет иметь истинное логическое значение, а не само значение d.

Ответы [ 12 ]

196 голосов
/ 20 января 2010

См. оценка короткого замыкания для объяснения. Это распространенный способ реализации этих операторов; он не уникален для JavaScript.

169 голосов
/ 22 июня 2010

Это сделано для присвоения значения по умолчанию , в данном случае значения y, если переменная x равна falsy .

Логические операторы в JavaScript могут возвращать операнд, и не всегда логический результат, как в других языках.

Оператор логического ИЛИ (||) возвращает значение своего второго операнда, если первый опциональный, в противном случае возвращается значение первого операнда.

Например:

"foo" || "bar"; // returns "foo"
false || "bar"; // returns "bar"

Falsy значения - это те, которые приводят к false при использовании в логическом контексте, и это 0, null, undefined, пустая строка, NaN и конечно false.

144 голосов
/ 22 июня 2010

Javacript использует оценку короткого замыкания для логических операторов || и &&. Однако он отличается от других языков тем, что возвращает результат последнего значения, остановившего выполнение, вместо значения true или false.

Следующие значения считаются ложными в JavaScript.

  • ложь
  • нуль
  • "" (пустая строка)
  • 0
  • Nan
  • неопределенный

Игнорируя правила приоритета оператора и упрощая простоту, в следующих примерах показано, какое значение остановило оценку и в результате возвращается.

false || null || "" || 0 || NaN || "Hello" || undefined // "Hello"

Первые 5 значений вплоть до NaN являются ложными, поэтому все они оцениваются слева направо, пока не встретится первое истинное значение - "Hello", которое делает все выражение истинным, поэтому все дальнейшее повышение не будет оцениваться, и "Hello" возвращается в результате выражения. Аналогично, в этом случае:

1 && [] && {} && true && "World" && null && 2010 // null

Первые 5 значений верны и оцениваются до тех пор, пока не встретится первое ложное значение (null), которое делает выражение ложным, поэтому 2010 больше не оценивается, а null возвращается в результате выражения.

В приведенном вами примере используется это свойство JavaScript для выполнения назначения. Его можно использовать где угодно, где вам нужно получить первое истинное или ложное значение среди набора значений. Приведенный ниже код назначит значение "Hello" для b, поскольку это упрощает назначение значения по умолчанию вместо выполнения проверок if-else.

var a = false;
var b = a || "Hello";

Вы можете назвать приведенный ниже пример эксплуатацией этой функции, и я считаю, что это затрудняет чтение кода.

var messages = 0;
var newMessagesText = "You have " + messages + " messages.";
var noNewMessagesText = "Sorry, you have no new messages.";
alert((messages && newMessagesText) || noNewMessagesText);

Внутри предупреждения мы проверяем, является ли messages ложным, и если да, то оцениваем и возвращаем noNewMessagesText, в противном случае оцениваем и возвращаем newMessagesText Поскольку в этом примере это неверно, мы останавливаемся на noNewMessagesText и предупреждаем "Sorry, you have no new messages.".

46 голосов
/ 20 января 2010

Переменные Javascript не являются типизированными, поэтому f можно присвоить целочисленное значение, даже если оно было назначено с помощью логических операторов.

f присваивается ближайшее значение, которое не эквивалентно ложному . Итак, 0, false, null, undefined, все передаются:

alert(null || undefined || false || '' || 0 || 4 || 'bar'); // alerts '4'
29 голосов
/ 20 января 2010

В этом нет никакой магии. Булевы выражения типа a || b || c || d лениво оцениваются. Interpeter ищет значение a, оно не определено, поэтому оно ложно, поэтому оно движется дальше, затем оно видит b, равное нулю, которое все еще дает ложный результат, поэтому оно движется дальше, затем оно видит c - та же история. Наконец, он видит d и говорит: «Да, это не ноль, поэтому у меня есть свой результат», и он присваивает его конечной переменной.

Этот прием будет работать на всех динамических языках, которые лениво оценивают логические выражения при коротком замыкании. В статических языках он не будет компилироваться (ошибка типа). На языках, которые стремятся оценить логические выражения, он вернет логическое значение (т. Е. В данном случае true).

9 голосов
/ 03 июня 2016

На этот вопрос уже получено несколько хороших ответов.

Таким образом, в этом методе используется особенность компиляции языка. То есть JavaScript «закорачивает» оценку булевых операторов и возвращает значение, связанное либо с первым непустым значением переменной, либо с тем, что содержит последняя переменная. См. Объяснение Анурага тех значений, которые будут оцениваться как ложные.

Использование этой техники не является хорошей практикой по нескольким причинам; однако.

  1. Читаемость кода: при этом используются логические операторы, и если поведение того, как это компилируется, не понимается, то ожидаемый результат будет логическим значением.
  2. Стабильность: при этом используется функция компиляции языка, которая несовместима между несколькими языками, и из-за этого она может потенциально стать целью изменений в будущем.
  3. Документированные функции: существует альтернатива, которая удовлетворяет эту потребность и совместима с другими языками. Это будет троичный оператор:

    ()? значение 1: значение 2.

Использование троичного оператора требует немного большего набора текста, но оно четко различает оцениваемое логическое выражение и присваиваемое значение. Кроме того, он может быть объединен в цепочку, поэтому типы выполняемых по умолчанию назначений могут быть воссозданы.

var a;
var b = null;
var c = undefined;
var d = 4;
var e = 'five';

var f =  ( a ) ? a : 
                ( b ) ? b :
                       ( c ) ? c :
                              ( d ) ? d :
                                      e;

alert(f); // 4
5 голосов
/ 15 марта 2016

Возвращаемый результат первое истинное значение .

Если все ложно, вернуть последнее ложное значение.

Пример: -

  null || undefined || false || 0 || 'apple'  // Return apple
4 голосов
/ 22 июня 2010

Он устанавливает новую переменную (z) либо в значение x, если оно "истинное" (ненулевое, допустимый объект / массив / функция / что бы то ни было) или y в противном случае Это относительно распространенный способ предоставления значения по умолчанию в случае, если x не существует.

Например, если у вас есть функция, которая принимает необязательный параметр обратного вызова, вы можете предоставить обратный вызов по умолчанию, который ничего не делает:

function doSomething(data, callback) {
    callback = callback || function() {};
    // do stuff with data
    callback(); // callback will always exist
}
1 голос
/ 22 декабря 2017

Это называется оператор короткого замыкания.

Оценка короткого замыкания говорит, что второй аргумент выполняется или оценивается, только если первого аргумента недостаточно для определения значения выражения. когда первый аргумент функции OR (||) принимает значение true, общее значение должно быть истинным.

Может также использоваться для установки значения по умолчанию для аргумента функции.

function theSameOldFoo(name){ 
  name = name || 'Bar' ;
  console.log("My best friend's name is " + name);
}
theSameOldFoo();  // My best friend's name is Bar
theSameOldFoo('Bhaskar');  // My best friend's name is Bhaskar`
1 голос
/ 22 июня 2010

Это означает, что если установлено x, значение для z будет x, в противном случае, если установлено y, его значение будет установлено как значение z.

это то же самое, что и

if(x)
  z = x;
else
  z = y;

Это возможно, потому что логические операторы в JavaScript не возвращают логические значения, но значение последнего элемента, необходимого для завершения операции (в предложении OR это будет первое не ложное значение, в предложении AND это будет последний). Если операция завершилась неудачно, то возвращается false.

...