JavaScript OR (||) объяснение назначения переменной
Учитывая этот фрагмент 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
будет назначено ближайшее значение (слева направо) первой переменной, которая имеет значение, которое не является ни нулевым, ни неопределенным, но мне не удалось найти много справочного материала об этой технике, и я видел, что она использовала много,
Кроме того, эта техника специфична для JavaScript? Я знаю, что сделать что-то подобное в PHP приведет к f
имеющий истинное логическое значение, а не значение d
сам.
12 ответов
См. Оценку короткого замыкания для объяснения. Это распространенный способ реализации этих операторов; это не уникально для JavaScript.
Это сделано для назначения значения по умолчанию, в этом случае значение y
если x
переменная ложь.
Логические операторы в JavaScript могут возвращать операнд, а не всегда логический результат, как в других языках.
Оператор логического ИЛИ (||
) возвращает значение своего второго операнда, если первый является ложным, в противном случае возвращается значение первого операнда.
Например:
"foo" || "bar"; // returns "foo"
false || "bar"; // returns "bar"
Ложные ценности - это те, кто принуждает false
при использовании в логическом контексте, и они 0
, null
, undefined
пустая строка, NaN
и конечно false
,
Javacript использует оценку короткого замыкания для логических операторов ||
а также &&
, Однако он отличается от других языков тем, что возвращает результат последнего значения, остановившего выполнение, вместо true
, или же false
значение.
Следующие значения считаются ложными в JavaScript.
- ложный
- ноль
""
(пустой строки)- 0
- бабушка
- не определено
Игнорируя правила приоритета операторов и сохраняя простоту, в следующих примерах показано, какое значение остановило оценку и возвращается в результате.
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."
,
Переменные Javascript не являются типизированными, поэтому f можно присвоить целочисленное значение, даже если оно было назначено с помощью логических операторов.
f присваивается ближайшее значение, которое не эквивалентно ложному. Итак, 0, false, null, undefined, все передаются:
alert(null || undefined || false || '' || 0 || 4 || 'bar'); // alerts '4'
В этом нет никакой магии. Логические выражения типа a || b || c || d
лениво оцениваются. Интерпетер ищет значение a
, он не определен, поэтому он ложный, поэтому он движется дальше, то он видит b
который равен нулю, который все еще дает ложный результат, поэтому он движется дальше, то он видит c
- та же история. Наконец то видит d
и говорит "да, это не нуль, поэтому у меня есть свой результат", и он присваивает его конечной переменной.
Этот трюк будет работать на всех динамических языках, которые лениво оценивают логические выражения при коротком замыкании. В статических языках он не будет компилироваться (ошибка типа). В языках, которые стремятся оценить логические выражения, он вернет логическое значение (т. Е. В данном случае true).
Этот вопрос уже получил несколько хороших ответов.
Таким образом, этот метод использует возможность компилирования языка. То есть JavaScript "закорачивает" оценку булевых операторов и возвращает значение, связанное либо с первым непустым значением переменной, либо с чем-либо, что содержит последняя переменная. См. Объяснение Анурага тех ценностей, которые будут оцениваться как ложные.
Использование этой техники не является хорошей практикой по нескольким причинам; тем не мение.
- Читаемость кода: это использует логические операторы, и если поведение того, как это компилируется, не понято, то ожидаемый результат будет логическим значением.
- Стабильность: при этом используется функция компиляции языка, которая несовместима между несколькими языками, и из-за этого она потенциально может быть предназначена для изменений в будущем.
Документированные функции: существует альтернатива, которая удовлетворяет эту потребность и совместима с другими языками. Это будет троичный оператор:
()? значение 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
Вернуть вывод первого истинного значения.
Если все ложно, верните последнее ложное значение.
Пример:-
null || undefined || false || 0 || 'apple' // Return apple
Это называется оператор короткого замыкания.
Оценка короткого замыкания говорит, что второй аргумент выполняется или оценивается, только если первого аргумента недостаточно для определения значения выражения. когда первый аргумент функции 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`
Это установка новой переменной (z
) либо к значению x
если это "правда" (ненулевой, допустимый объект / массив / функция / что бы то ни было) или y
иначе. Это довольно распространенный способ предоставления значения по умолчанию в случае x
не существует
Например, если у вас есть функция, которая принимает необязательный параметр обратного вызова, вы можете предоставить обратный вызов по умолчанию, который ничего не делает:
function doSomething(data, callback) {
callback = callback || function() {};
// do stuff with data
callback(); // callback will always exist
}
Это означает, что если x
установлено значение для z
будет x
иначе если y
то его значение будет установлено как z
ценность.
это так же, как
if(x)
z = x;
else
z = y;
Это возможно, потому что логические операторы в JavaScript не возвращают логические значения, но значение последнего элемента, необходимого для завершения операции (в предложении ИЛИ это будет первое не ложное значение, в предложении И это будет последнее). Если операция не удалась, то false
возвращается
Согласно сообщению в блоге Билла Хиггинса; идиома логического ИЛИ назначения Javascript (февраль 2007 г.), это поведение верно с версии 1.2 (по крайней мере)
Он также предлагает другое использование для этого (цитируется): "облегченная нормализация различий между браузерами"
// determine upon which element a Javascript event (e) occurred
var target = /*w3c*/ e.target || /*IE*/ e.srcElement;
Он будет оценивать X и, если X не равен NULL, пустой строке или 0 (логическое ложное значение), то он назначит его для z. Если X - ноль, пустая строка или 0 (логическое ложь), тогда он назначит y для z.
var x = '';
var y = 'bob';
var z = x || y;
alert(z);
Будет выводить "Боб";