Я видел эту конструкцию для получения ширины области просмотра браузера:
function () { return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; }
Я понимаю включенные причуды браузера. То, что я не понимаю, то, почему ||
возвращает значение. Таким образом, я попробовал это alert(undefined || 0 || 3);
и конечно же, это предупреждает 3
. Я нахожу это причудливым, потому что я ожидаю true
или false
. Кто-либо мог объяснить, что продолжается?
Посмотрите раздел стандартов ECMAScript 11.11 Бинарные логические операторы
Произведение LogicalORExpression : LogicalORExpression || LogicalANDExpression оценивается следующим образом следующим образом:
1.Оценить LogicalORExpression.
2.Вызов GetValue(Result(1)).
3.Вызвать ToBoolean(Result(2)).
4.Если результат(3) истинен, вернуть результат(2).
5.Evaluate LogicalANDExpression.
6.Вызвать GetValue(Result(5)).
7.Возвращаем Result(6).
Таким образом, оценивается булево преобразование каждого операнда, но возвращается фактическое значение операнда.
Если вы хотите узнать, как Javascript преобразует значения в булево, смотрите раздел 9.2 ToBoolean
Функция ИЛИ - это оценка с коротким замыканием ИЛИ - она возвращает первый элемент, который не является ложным, или последний элемент, который не является ложным, в противном случае.
На самом деле это очень полезно, поэтому вы можете писать выражения вроде
a = a || someValue;
, которые аналогичны
if (a==null)
a = someValue;
Оператор JavaScript ||
определен так, чтобы возвращать левое значение, если оно оценивается как истинное значение, в противном случае - правое значение вместо того, чтобы возвращать само истинное
. Именно так это определено в спецификации.
Я знаю, что иногда это может раздражать, вы можете случайно получить ссылку на то, за что не хотите держаться, но это также позволяет использовать удобный трюк, который есть в вашем примере. У всего есть свои плюсы и минусы.
Не думайте об этом как о «или». Это больше похоже на устройство управления потоком внутри выражения. Значение a || выражение - это значение первого "истинного" подвыражения. Таким образом, вычисление серии подвыражений останавливается в какой-то момент, как если бы
expr1 || expr2 || expr3
было
(function() {
var rv = expr1;
if (rv) return rv;
rv = expr2;
if (rv) return rv;
return expr3;
})()
Так оно и есть задумано. ||
, как и &&
, является оператором короткого замыкания, выражения вычисляются по порядку, они останавливаются после того, как выражение соответствует критериям, и выдают результат выражения. То же самое и с &&
:
var myObj = { "Test": { "Foo":"Bar" } };
var myObj2 = { "Foo": "Bar" };
alert(myObj.Test && myObj.Test.Foo); // will alert "Bar";
alert(myObj2.Test && myObj2.Test.Foo); // will alert undefined;
Некоторые значения, такие как ноль, ""
или undefined
, обрабатываются как ложные. Все остальное верно, поэтому оператор ||
просто возвращает первое ненулевое (то есть истинное) значение в заданной паре. Это полезно для таких приемов, как приведенный выше код, но я предполагаю, что это не было добавлено в язык только для того, чтобы вы могли пропустить нечетный оператор if.
Я подозреваю, что это могло быть связано с изменением производительности, поскольку языки более высокого уровня (такие как BASIC ... да, возможно, странное определение более высокого уровня) использовали фиксированные константы для истинного и ложного - часто 0 и -1 или 0 и 1.