Matrizes vazias são verdadeiras, mas também são iguais a falsas.
var arr = [];
console.log('Array:', arr);
if (arr) console.log("It's true!");
if (arr == false) console.log("It's false!");
if (arr && arr == false) console.log("...what??");
Eu acho que isso se deve à conversão implícita operada pelo operador de igualdade.
Alguém pode explicar o que está acontecendo nos bastidores?
javascript
Patonza
fonte
fonte
arr == true
isso não é avaliado como verdadeiro ;-) #===
. Então, se você quiser testar o vazio de uma matriz, usearr === []
arr === []
, pois isso SEMPRE retornará falso, pois o lado direito está instanciando uma nova matriz e a variável à esquerda não pode se referir a algo que você acabou de criar. O vazio do teste deve ser feito olhando para cimaarr.length === 0
.Respostas:
Você está testando coisas diferentes aqui.
if (arr)
O objeto chamado (Matriz é a instância do Objeto em JS) verificará se o objeto está presente e retorna verdadeiro / falso.Quando você chama,
if (arr == false)
compara os valores desse objeto e ofalse
valor primitivo . Internamente,arr.toString()
é chamado, que retorna uma string vazia""
.Isso ocorre porque o
toString
retorno da matriz é chamadoArray.join()
e a string vazia é um dos valores falsos no JavaScript.fonte
Boolean([])
retornatrue
?Em relação à linha:
Talvez isso ajude:
O que eu acredito que está acontecendo é que o booleano
false
é coagido0
para comparação com um objeto (o lado esquerdo). O objeto é coagido a uma sequência (a sequência vazia). Então, a cadeia vazia também é coagida em um número, ou seja, zero. E assim a comparação final é0
==0
, que étrue
.Editar: Veja esta seção da especificação para obter detalhes sobre exatamente como isso funciona.
Aqui está o que está acontecendo, começando na regra 1:
A próxima regra que se aplica é # 19:
O resultado de
ToNumber(false)
é0
, então agora temos:Mais uma vez, a regra 1 nos diz que devemos pular para a etapa 14, mas a próxima etapa que se aplica realmente é a 21:
O resultado de
ToPrimitive([])
é a string vazia, então agora temos:Mais uma vez, a regra 1 nos diz que devemos pular para a etapa 14, mas a próxima etapa que realmente se aplica é a 17:
O resultado de
ToNumber("")
é0
, o que nos deixa com:Agora, os dois valores têm o mesmo tipo, portanto, as etapas continuam do 1 ao 7, que diz:
Então, voltamos
true
.Em resumo:
fonte
[] == 0
verdadeiras , 0 é falsey e, no entanto, é verdade. Entendo como isso acontece com base na sua explicação sobre as especificações, mas parece um comportamento estranho da linguagem do ponto de vista lógico.Para complementar a resposta de Wayne e tentar explicar por que
ToPrimitive([])
retorna""
, vale a pena considerar dois tipos possíveis de respostas para a pergunta 'por que'. O primeiro tipo de resposta é: "porque a especificação diz que é assim que o JavaScript se comportará". Na especificação do ES5, seção 9.1 , que descreve o resultado de ToPrimitive como um valor padrão para um Objeto:Seção 8.12.8 descreve o
[[DefaultValue]]
método. Esse método usa uma "dica" como argumento e a dica pode ser String ou Number. Para simplificar o assunto dispensando alguns detalhes, se a dica for String,[[DefaultValue]]
retornará o valor detoString()
se ele existir e retornará um valor primitivo e, caso contrário, retornará o valor devalueOf()
. Se a dica for Number, as prioridades detoString()
evalueOf()
serão revertidas para quevalueOf()
seja chamado primeiro e seu valor retornado se for um primitivo. Portanto, se[[DefaultValue]]
retorna o resultadotoString()
ouvalueOf()
depende do PreferredType especificado para o objeto e se essas funções retornam ou não valores primitivos.O
valueOf()
método Object padrão apenas retorna o próprio objeto, o que significa que, a menos que uma classe substitua o método padrão,valueOf()
apenas retorna o próprio objeto. Este é o casoArray
.[].valueOf()
retorna o[]
próprio objeto . Como umArray
objeto não é primitivo, a[[DefaultValue]]
dica é irrelevante: o valor de retorno para uma matriz será o valor detoString()
.Para citar o JavaScript de David Flanagan : The Definitive Guide , que, a propósito, é um livro excelente que deve ser o primeiro lugar de todos para obter respostas para esses tipos de perguntas:
O segundo tipo de resposta para a pergunta "por que", exceto "porque a especificação diz", fornece algumas explicações sobre por que o comportamento faz sentido da perspectiva do design. Sobre esta questão, só posso especular. Primeiro, como converter uma matriz em um número? A única possibilidade sensata que consigo pensar seria converter uma matriz vazia em 0 e qualquer matriz não vazia em 1. Mas, como a resposta de Wayne revelou, uma matriz vazia será convertida em 0 para muitos tipos de comparações de qualquer maneira. Além disso, é difícil pensar em um valor de retorno primitivo sensível para Array.valueOf (). Portanto, pode-se argumentar que faz mais sentido ter
Array.valueOf()
o padrão e retornar a própria matriz, levandotoString()
ao resultado usado pelo ToPrimitive. Faz mais sentido converter uma matriz em uma cadeia de caracteres do que em um número.Além disso, como sugerido pela citação de Flanagan, essa decisão de design permite certos tipos de comportamentos benéficos. Por exemplo:
Esse comportamento permite comparar uma matriz de elemento único com números e obter o resultado esperado.
fonte
fonte
Em if (arr), é sempre avaliado (ToBoolean) como true se arr for um objeto, pois todos os objetos em JavaScript são verdadeiros . (null não é um objeto!)
[] == false
é avaliado em abordagem iterativa. Inicialmente, se um lado de==
é primitivo e o outro é objeto, ele converte o objeto em primitivo no início e, em seguida, converte os dois lados em Number se ambos os lados não estiveremstring
(a comparação de strings é usada se os dois lados forem strings). Portanto, a comparação é iterada como,[] == false
->'' == false
->0 == 0
->true
.fonte
Exemplo:
Isso acontece porque
[]
está umArray
objeto vazio →ToPrimitive([])
→ "" →ToNumber("")
→0
ToNumber(false)
→ 0fonte
Uma matriz com elementos (independentemente de 0, falso ou outra matriz vazia), sempre resolve
true
usar a Comparação de Igualdade Abstrata==
.Mas, usando uma comparação estrita de igualdade
===
, você está tentando avaliar o conteúdo da variável e o tipo de dados, por isso:fonte
Você pode esvaziar uma matriz JavaScript referenciando-a em uma nova matriz, usando
list = []
ou excluindo os elementos da matriz atualmente referenciadalist.length = 0
.Origem: JavaScript Empty Array
fonte
Nenhuma das opções acima me ajudou, ao tentar usar o plug-in de mapeamento knockout.js, talvez porque um "array vazio" não esteja realmente vazio.
Acabei usando:
data-bind="if: arr().length"
qual fez o truque.Isso é específico do nocaute, não da pergunta do OP, mas talvez ajude alguém a navegar aqui em uma situação semelhante.
fonte