Что такое оператор двойной трубы ( ||)?
Оператор двойной трубы ( ||) является логическим ORоператором . На большинстве языков это работает следующим образом:
- Если первое значение
false, оно проверяет второе значение. Если это так true, он возвращается, trueи если это так false, он возвращается false.
- Если первое значение
true, оно всегда возвращается true, независимо от того, какое второе значение.
Так что в основном это работает как эта функция:
function or(x, y) {
if (x) {
return true;
} else if (y) {
return true;
} else {
return false;
}
}
Если вы все еще не понимаете, посмотрите на эту таблицу:
| true false
------+---------------
true | true true
false | true false
Другими словами, это только ложь, когда оба значения ложны.
Чем он отличается в JavaScript?
JavaScript немного отличается, потому что это слабо типизированный язык . В этом случае это означает, что вы можете использовать ||оператор со значениями, которые не являются логическими. Хотя это не имеет смысла, вы можете использовать этот оператор, например, с функцией и объектом:
(function(){}) || {}
Что там происходит?
Если значения не являются логическими, JavaScript делает неявное преобразование в логические . Это означает , что если значение falsey (например 0, "", null, undefined(смотри также все значения falsey в JavaScript )), это будет рассматриваться как false; в противном случае это рассматривается как true.
Так что приведенный выше пример должен дать true, потому что пустая функция верна. Ну, это не так. Возвращает пустую функцию. Это потому, что ||оператор JavaScript не работает, как я писал в начале. Работает следующим образом:
- Если первое значение равно Falsey , оно возвращает второе значение .
- Если первое значение верно , оно возвращает первое значение .
Удивлены? На самом деле, он «совместим» с традиционным ||оператором. Это можно записать как следующую функцию:
function or(x, y) {
if (x) {
return x;
} else {
return y;
}
}
Если вы передаете истинное значение как x, оно возвращает x, то есть истинное значение. Так что, если вы используете его позже в ifпункте:
(function(x, y) {
var eitherXorY = x || y;
if (eitherXorY) {
console.log("Either x or y is truthy.");
} else {
console.log("Neither x nor y is truthy");
}
}(true/*, undefined*/));
Вы получаете "Either x or y is truthy.".
Если бы xбыл фальсей, eitherXorYбыл бы y. В этом случае вы получите , "Either x or y is truthy."если yбыл truthy; в противном случае вы получите "Neither x nor y is truthy".
Актуальный вопрос
Теперь, когда вы знаете, как ||работает оператор, вы, вероятно, сможете сами разобраться, что это x = x || yзначит. Если xправдиво, xназначено x, так что на самом деле ничего не происходит; в противном случае yназначается x. Обычно используется для определения параметров по умолчанию в функциях. Тем не менее, это часто считается плохой практикой программирования , потому что она не позволяет вам передавать значение Фальси (что не обязательно undefinedили null) в качестве параметра. Рассмотрим следующий пример:
function badFunction(/* boolean */flagA) {
flagA = flagA || true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
Это выглядит актуально с первого взгляда. Тем не менее, что произойдет, если вы передадите в falseкачестве flagAпараметра (поскольку это логическое значение, т. Е. Может быть trueили false)? Это стало бы true. В этом примере нет способа установить flagAзначение false.
Лучше было бы явно проверить, flagAесть ли undefined, вот так:
function goodFunction(/* boolean */flagA) {
flagA = typeof flagA !== "undefined" ? flagA : true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
Хотя он длиннее, он всегда работает и его легче понять.
Вы также можете использовать синтаксис ES6 для параметров функций по умолчанию , но учтите, что он не работает в старых браузерах (например, IE). Если вы хотите поддерживать эти браузеры, вы должны перенести свой код с Babel .
Смотрите также Логические операторы на MDN .
falsy, а не простоundefined. Количество раз, которое я виделdoWeDoIt = doWeDoIt || true, достаточно, чтобы заставить меня плакать. (то естьdoWeDoItтеперь никогда не будетfalse)