JavaScript OU (||) explicação de atribuição de variável

Dado este trecho de 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 

Alguém pode me explicar o que esta técnica é chamada (meu melhor palpite é no título desta pergunta!)? E como / porque funciona exatamente?

Meu entendimento é que a variável f receberá o valor mais próximo (da esquerda para a direita) da primeira variável que tem um valor que não é nulo ou indefinido, mas não consegui encontrar muito material de referência sobre essa técnica e já vi isso muito usado.

Além disso, esta técnica é específica para JavaScript? Eu sei que fazer algo semelhante no PHP resultaria em f ter um valor booleano verdadeiro, em vez do valor de d si.

Veja a avaliação de curto-circuito para a explicação. É uma maneira comum de implementar esses operadores; não é exclusivo para JavaScript.

Isso é feito para atribuir um valor padrão , neste caso, o valor de y , se a variável x for falsa .

Os operadores booleanos em JavaScript podem retornar um operando e nem sempre um resultado booleano como em outros idiomas.

O operador OR Lógico ( || ) retorna o valor do seu segundo operando, se o primeiro for falso, caso contrário, o valor do primeiro operando é retornado.

Por exemplo:

 "foo" || "bar"; // returns "foo" false || "bar"; // returns "bar" 

Os valores de paralisia são aqueles que coagulam para false quando usados ​​no contexto booleano, e são 0 , null , undefined , uma string vazia, NaN e, claro, false .

Javacript usa avaliação de curto-circuito para operadores lógicos || e && . No entanto, é diferente de outros idiomas, pois retorna o resultado do último valor que interrompeu a execução, em vez de um valor true ou false .

Os seguintes valores são considerados falsos em JavaScript.

  • falso
  • nulo
  • "" (string vazia)
  • 0
  • Nan
  • Indefinido

Ignorando as regras de precedência do operador e mantendo as coisas simples, os exemplos a seguir mostram qual valor parou a avaliação e é retornado como resultado.

 false || null || "" || 0 || NaN || "Hello" || undefined // "Hello" 

Os primeiros 5 valores até NaN são falsos, então todos são avaliados da esquerda para a direita, até encontrar o primeiro valor geral – "Hello" que torna toda a expressão verdadeira, então qualquer coisa acima não será avaliada, e "Hello" retornou como resultado da expressão. Da mesma forma, neste caso:

 1 && [] && {} && true && "World" && null && 2010 // null 

Os primeiros 5 valores são todos verdadeiros e são avaliados até encontrar o primeiro valor falso ( null ), o que torna a expressão falsa, então 2010 não é mais avaliado, e null é retornado como resultado da expressão.

O exemplo que você deu é usar essa propriedade do JavaScript para realizar uma atribuição. Ele pode ser usado em qualquer lugar onde você precisa obter o primeiro valor falso ou falso entre um conjunto de valores. Este código abaixo irá atribuir o valor "Hello" para b , pois facilita a atribuição de um valor padrão, em vez de fazer verificações if-else.

 var a = false; var b = a || "Hello"; 

Você poderia chamar o exemplo abaixo de uma exploração desse recurso, e acredito que dificulte a leitura do código.

 var messages = 0; var newMessagesText = "You have " + messages + " messages."; var noNewMessagesText = "Sorry, you have no new messages."; alert((messages && newMessagesText) || noNewMessagesText); 

Dentro do alerta, verificamos se as messages são falsas e, se sim, então noNewMessagesText e retornemos noNewMessagesText , caso contrário newMessagesText e retornemos newMessagesText . Como é falso nesse exemplo, paramos no noNewMessagesText e alertamos "Sorry, you have no new messages." .

Variáveis ​​JavaScript não são digitadas, portanto, f pode ser atribuído a um valor inteiro mesmo que tenha sido atribuído através de operadores booleanos.

f é atribuído o valor mais próximo que não é equivalente a falso . Então, 0, falso, nulo, indefinido, são todos ignorados:

 alert(null || undefined || false || '' || 0 || 4 || 'bar'); // alerts '4' 

Não há mágica para isso. Expressões booleanas como a || b || c || d a || b || c || d a || b || c || d são avaliados preguiçosamente. Interpeter procura o valor de a , ele é indefinido então é falso, então ele se move, então ele vê b que é null, que ainda dá um resultado falso, então ele segue em frente, então ele vê c – mesma história. Finalmente, ele vê d e diz ‘huh, não é null, então eu tenho o meu resultado’ e atribui à variável final.

Esse truque funcionará em todas as linguagens dinâmicas que fazem a avaliação de curto-circuito das expressões booleanas. Em linguagens estáticas não compilará (digite error). Em linguagens que estão ansiosas em avaliar expressões booleanas, ele retornará valor lógico (ou seja, verdadeiro neste caso).

Esta questão já recebeu várias boas respostas.

Em resumo, esta técnica está aproveitando uma característica de como a linguagem é compilada. Ou seja, o JavaScript “provoca um curto-circuito” na avaliação dos operadores booleanos e retornará o valor associado ao primeiro valor de variável não-falso ou qualquer que seja a última variável. Veja a explicação da Anurag sobre esses valores que serão avaliados como falsos.

Usar essa técnica não é uma boa prática por vários motivos; Contudo.

  1. Legibilidade do código: Isso é usando operadores booleanos e, se o comportamento de como ele compila não for entendido, o resultado esperado seria um valor booleano.
  2. Estabilidade: Isso está usando um recurso de como a linguagem é compilada, que é inconsistente em vários idiomas e, devido a isso, é algo que poderia ser alvo de alterações no futuro.
  3. Recursos documentados: Existe uma alternativa existente que atende a essa necessidade e é consistente em mais idiomas. Este seria o operador ternário:

    () valor 1: valor 2.

O uso do operador ternário requer um pouco mais de digitação, mas distingue claramente entre a expressão booleana que está sendo avaliada e o valor atribuído. Além disso, ele pode ser encadeado, de modo que os tipos de atribuições padrão que estão sendo executados acima possam ser recriados.

 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 

É definir a nova variável ( z ) como o valor de x se for “truthy” (diferente de zero, um object / matriz / function válida / o que quer que seja) ou y . É uma maneira relativamente comum de fornecer um valor padrão no caso x não existir.

Por exemplo, se você tiver uma function que usa um parâmetro de retorno de chamada opcional, poderá fornecer um retorno de chamada padrão que não faz nada:

 function doSomething(data, callback) { callback = callback || function() {}; // do stuff with data callback(); // callback will always exist } 

Retorna o primeiro valor verdadeiro da saída.

Se todos forem falsos, retorne o último valor falso.

Exemplo:-

  null || undefined || false || 0 || 'apple' // Return apple 

Isso significa que, se x for definido, o valor de z será x , caso contrário, se y for definido, seu valor será definido como o valor de z .

é o mesmo que

 if(x) z = x; else z = y; 

É possível porque operadores lógicos em JavaScript não retornam valores booleanos, mas o valor do último elemento necessário para completar a operação (em uma sentença OR seria o primeiro valor não falso, em uma sentença AND seria o último ). Se a operação falhar, será retornado false .

Seu chamado operador de circuito curto.

A avaliação de curto-circuito diz que o segundo argumento é executado ou avaliado apenas se o primeiro argumento não for suficiente para determinar o valor da expressão. quando o primeiro argumento da function OR (||) for avaliado como true, o valor geral deverá ser verdadeiro.

Também pode ser usado para definir um valor padrão para o argumento de function.

 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` 

Ele irá avaliar X e, se X não for nulo, a string vazia, ou 0 (lógico falso), então irá atribuí-lo a z. Se X for nulo, a string vazia, ou 0 (lógico falso), então irá atribuir y para z.

 var x = ''; var y = 'bob'; var z = x || y; alert(z); 

Vai produzir ‘bob’;

De acordo com o post do blog de Bill Higgins ; o idioma lógico ou de atribuição de Javascript (fevereiro de 2007), esse comportamento é verdadeiro a partir da v1.2 (pelo menos)

Ele também sugere outro uso para ele (citado): ” normalização leve das diferenças entre navegadores

 // determine upon which element a Javascript event (e) occurred var target = /*w3c*/ e.target || /*IE*/ e.srcElement;