O que é o operador de tubo duplo ( ||)?
O operador de canal duplo ( ||) é o operador lógicoOR . Na maioria dos idiomas , funciona da seguinte maneira:
- Se o primeiro valor for
false, ele verifica o segundo valor. Se for true, ele retorna truee se é false, ele retorna false.
- Se o primeiro valor for
true, ele sempre retornará true, independentemente do segundo valor.
Então, basicamente, funciona como esta função:
function or(x, y) {
if (x) {
return true;
} else if (y) {
return true;
} else {
return false;
}
}
Se você ainda não entende, veja esta tabela:
| true false
------+---------------
true | true true
false | true false
Em outras palavras, só é falso quando ambos os valores são falsos.
Como é diferente em JavaScript?
O JavaScript é um pouco diferente, porque é uma linguagem pouco digitada . Nesse caso, significa que você pode usar o ||operador com valores que não são booleanos. Embora não faça sentido, você pode usar este operador com, por exemplo, uma função e um objeto:
(function(){}) || {}
O que acontece lá?
Se os valores não forem booleanos, o JavaScript fará uma conversão implícita em booleano . Isso significa que, se o valor for Falsey (por exemplo 0, "", null, undefined(ver também Todos os valores Falsey no JavaScript )), que serão tratadas como false; caso contrário, é tratado como true.
Portanto, o exemplo acima deve dar true, porque a função vazia é verdadeira. Bem, não. Retorna a função vazia. Isso ||ocorre porque o operador do JavaScript não funciona como eu escrevi no começo. Funciona da seguinte maneira:
- Se o primeiro valor for falsey , ele retornará o segundo valor .
- Se o primeiro valor for verdadeiro , ele retornará o primeiro valor .
Surpreso? Na verdade, é "compatível" com o ||operador tradicional . Pode ser escrito da seguinte forma:
function or(x, y) {
if (x) {
return x;
} else {
return y;
}
}
Se você passar um valor verdadeiro como x, ele retornará x, ou seja, um valor verdadeiro. Portanto, se você usá-lo posteriormente na ifcláusula:
(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*/));
você recebe "Either x or y is truthy.".
Se xfosse falsey, eitherXorYseria y. Nesse caso, você obteria o "Either x or y is truthy."if yera verdade; caso contrário, você receberia "Neither x nor y is truthy".
A questão real
Agora, quando você souber como o ||operador funciona, provavelmente poderá entender por si mesmo o que x = x || ysignifica. Se xé verdade, xé atribuído a x, então, na verdade, nada acontece; caso contrário, yé atribuído a x. É comumente usado para definir parâmetros padrão nas funções. No entanto, muitas vezes é considerada uma má prática de programação , porque impede que você passe um valor de falsey (que não é necessariamente undefinedou null) como parâmetro. Considere o seguinte exemplo:
function badFunction(/* boolean */flagA) {
flagA = flagA || true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
Parece válido à primeira vista. No entanto, o que aconteceria se você passasse falsecomo flagAparâmetro (já que é booleano, ou seja, pode ser trueou false)? Isso se tornaria true. Neste exemplo, não há nenhuma maneira para definir flagAa false.
Seria uma idéia melhor verificar explicitamente se flagAé undefinedassim:
function goodFunction(/* boolean */flagA) {
flagA = typeof flagA !== "undefined" ? flagA : true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
Embora seja mais longo, sempre funciona e é mais fácil de entender.
Você também pode usar a sintaxe ES6 para os parâmetros de função padrão , mas observe que ela não funciona em navegadores mais antigos (como o IE). Se você deseja oferecer suporte a esses navegadores, transpile seu código com o Babel .
Consulte também Operadores lógicos no MDN .
falsy, não APENASundefined. A quantidade de vezes que eu vidoWeDoIt = doWeDoIt || true, é suficiente para me fazer chorar. (ou seja,doWeDoItvai agora nunca seráfalse)