Почему делает JavaScript ИЛИ возвращают значение кроме истинного/ложного?

Я видел эту конструкцию для получения ширины области просмотра браузера:

function () { return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; }

Я понимаю включенные причуды браузера. То, что я не понимаю, то, почему || возвращает значение. Таким образом, я попробовал это alert(undefined || 0 || 3); и конечно же, это предупреждает 3. Я нахожу это причудливым, потому что я ожидаю true или false. Кто-либо мог объяснить, что продолжается?

19
задан Fletcher Moore 3 June 2010 в 13:35
поделиться

6 ответов

Посмотрите раздел стандартов 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

18
ответ дан 30 November 2019 в 02:10
поделиться

Функция ИЛИ - это оценка с коротким замыканием ИЛИ - она ​​возвращает первый элемент, который не является ложным, или последний элемент, который не является ложным, в противном случае.

На самом деле это очень полезно, поэтому вы можете писать выражения вроде

a = a || someValue;

, которые аналогичны

if (a==null)
  a = someValue;
6
ответ дан 30 November 2019 в 02:10
поделиться

Оператор JavaScript || определен так, чтобы возвращать левое значение, если оно оценивается как истинное значение, в противном случае - правое значение вместо того, чтобы возвращать само истинное . Именно так это определено в спецификации.

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

23
ответ дан 30 November 2019 в 02:10
поделиться

Не думайте об этом как о «или». Это больше похоже на устройство управления потоком внутри выражения. Значение a || выражение - это значение первого "истинного" подвыражения. Таким образом, вычисление серии подвыражений останавливается в какой-то момент, как если бы

 expr1 || expr2 || expr3

было

 (function() {
   var rv = expr1;
   if (rv) return rv;
   rv = expr2;
   if (rv) return rv;
   return expr3;
 })()
13
ответ дан 30 November 2019 в 02:10
поделиться

Так оно и есть задумано. || , как и && , является оператором короткого замыкания, выражения вычисляются по порядку, они останавливаются после того, как выражение соответствует критериям, и выдают результат выражения. То же самое и с && :

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;
2
ответ дан 30 November 2019 в 02:10
поделиться

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

Я подозреваю, что это могло быть связано с изменением производительности, поскольку языки более высокого уровня (такие как BASIC ... да, возможно, странное определение более высокого уровня) использовали фиксированные константы для истинного и ложного - часто 0 и -1 или 0 и 1.

1
ответ дан 30 November 2019 в 02:10
поделиться