{}[true]
é [true]
e ![true]
deve ser false
.
Então, por que !{}[true]
avaliar para true
?
javascript
user2430508
fonte
fonte
var o = {}; o[true] === undefined
.{}[true] === [true]
de um console, é porque está tratando{}
como um bloco de código vazio, não como um objeto.{}
e({})
no seu console (ou{}[true]
e({})[true]
). Além disso, como ninguém mencionou, o objeto [true] é avaliado como objeto ["true"].Respostas:
Eu acredito que é porque plain
{}[true]
é analisado como um bloco de instrução vazio (não um objeto literal) seguido por uma matriz que contémtrue
, o que étrue
.Por outro lado, a aplicação do
!
operador faz com que o analisador interprete{}
como um objeto literal, para que o seguinte{}[true]
se torne um acesso de membro que retorneundefined
e!{}[true]
sejatrue
(como!undefined
étrue
).fonte
undefined
é falso (algo em que confiamos frequentemente -if (obj.maybeExists) ...
), por isso faz todo o sentido lógico que!undefined
é verdadeiro.null
de algumas línguas,!undefined
sendo igual aundefined
. Esse não é o caso do Javascript.not undefined
(!undefined
) deve, portanto, ser definido. Se algo é definido, geralmente é interpretado comotrue
.Porque
{}[true]
não retornatrue
, masundefined
, eundefined
é avaliado comofalse
:http://jsfiddle.net/67GEu/
fonte
{}[true]
em um console, obtém[true]
, porque o{}
é interpretado como um bloco de código vazio, não como um objeto. É tudo sobre o contexto e a ambiguidade de{}
.{key:"value"}[1,2,3];
também avalia[1,2,3]
?key:
) e uma string literal ("value"
), seguida por uma matriz. O analisador ainda não vê um objeto literal.alert()
ouconsole.log()
, ou atribuí-lo a uma variável, você está alterando o contexto, e é por isso que ele não se comporta da mesma maneira que digitado sozinho em um console.Porque
avalia
undefined
e!undefined
étrue
.From @schlingel:
true
é usado como chave e{}
como mapa de hash. Não existe uma propriedade com a chave,true
portanto ela retornaundefined
. Nãoundefined
étrue
, como esperado.Sessão do console ( Node.js
[0.10.17]
):No entanto, no console do Google Chrome :
Portanto, sem inconsistências. Você provavelmente está usando uma versão antiga da VM JavaScript. Para aqueles que precisam de mais evidências:
ATUALIZAR
Com o Firefox , ele também avalia
true
:fonte
eval('{}[true]')
digitar ou digitar no console. Então, por exemplo, als{}"test"
étest
ou mesmo{key:"value"}"test"
étest
.{}[true];
(com a;
) de retorno[true]
para você, porque aqui ele faz?O motivo da confusão se deve a um mal-entendido de sua primeira afirmação:
{}[true]
é[true]
O que você vê quando executa é o resultado de uma ambiguidade. O Javascript possui um conjunto definido de regras sobre como lidar com ambiguidades como essa e, nesse caso, divide o que você vê como uma declaração de sinalização em duas declarações separadas.
Portanto, o Javascript vê o código acima como duas instruções separadas: Primeiro, existe um
{}
e, depois, um totalmente separado[true]
. A segunda afirmação é o que está lhe dando o resultado[true]
. A primeira afirmação{}
é efetivamente totalmente ignorada.Você pode provar isso tentando o seguinte:
ou seja, colocar tudo entre colchetes para forçar o intérprete a lê-lo como uma única declaração.
Agora você verá que o valor real de sua declaração é
undefined
. (isso também nos ajudará mais tarde a entender a próxima parte)Agora sabemos que a parte inicial da sua pergunta é um arenque vermelho, então vamos para a parte final da pergunta:
Aqui, temos a mesma declaração, mas com um
!
anexo à frente.Nesse caso, as regras do Javascript dizem para avaliar a coisa toda como uma única instrução.
Consulte o que aconteceu quando colocamos a declaração anterior entre colchetes; nós temos
undefined
. Desta vez, estamos efetivamente fazendo a mesma coisa, mas colocando a!
frente dela. Portanto, seu código pode ser simplificado como!undefined
, o que étrue
.Espero que isso explique um pouco.
É um animal complexo, mas a lição a aprender aqui é usar colchetes em torno de suas declarações ao avaliá-las no console, para evitar resultados espúrios como este.
fonte
{}[true]
seja inválido exatamente, apenas ambíguo . Pode ser interpretado como "bloco de código vazio seguido por matriz literal" ou "literal de objeto sem propriedades, das quais uma propriedade está sendo acessada". Não sei se o primeiro é tecnicamente um caso de ASI (muitas línguas não colocariam ponto-e-vírgula lá de qualquer maneira), mas é a interpretação sensível ao contexto que é o cerne da questão.{}[true]
étrue
" eles disseram "{}[true]
é[true]
", que é uma das duas interpretações válidas da declaração ambígua.{}[true]
éundefined
. Para descobrir que escreva isso:ou simplesmente:
Nós sabemos que
!undefined
é issotrue
.Da resposta de @Benjamin Gruenbaum :
Mais informações podem ser encontradas nesta pergunta .
fonte
As respostas aqui são boas, aqui está um detalhamento do pseudo-código:
{}['whatever']
= bloco vazio, NewArray ('qualquer coisa') = NewArray ('qualquer coisa'){}[true]
= bloco vazio, NewArray (true) = NewArray (true)!{}['whatever']
= LogicalNOT (convertToBool (NewObject.whatever)) = LogicalNOT (convertToBool (indefinido)) = LogicalNOT (false) = true({}['whatever'])
= Agrupamento (NewObject.whatever) = Agrupamento (indefinido) = indefinidofonte
Isso acontece porque,
{}
no seu significado, não é uma apresentação literal deObject
, mas um escopo vazio (ou bloco de código vazio):Ele apenas avalia o código dentro do escopo e mostra sua matriz.
E do seu
Apenas converte para int esse escopo e retorna a mesma matriz true. Não há verificações de booleano neste código.
E se você tentar verificar o resultado
{}[true]
, obterá o seufalse
:Como não há mais escopo.
Portanto,
!
na sua pergunta, faça o mesmo:fonte
var x = {}; x[true]
.!
ele é interpretado como um objeto vazio, não como escopo, e essa é a discrepância.{}
é um objeto sem propriedades.[]
segue imediatamente um objeto, significa "Acessar uma propriedade com esse nome" e não "Criar uma matriz"true
é um booleano, mas está sendo usado como um nome de propriedade para que seja convertido em uma string ("true"
)true
(uma vez que não possui propriedades), portanto,{}['true']
éundefined
!undefined
lançaundefined
para um booleano (false
)false
transformatrue
.fonte
{}[true]
(sem outro contexto), não{}
é um objeto sem propriedades, é um bloco de código vazio.Você não está revertendo o valor disso.
Veja isto: Por que! True? 'false': 'true' retornando 'true'?
fonte
Vamos jogar um pouco mais!
Primeiro, vamos nos divertir!
Ok, vamos tentar entender esses comportamentos malucos, um por um:
1) Aqui, o
{}
é analisado como um bloco de código vazio. Sem uma atribuição, negação, agrupamento (entre parênteses) ou qualquer sintaxe que indique ao analisador que este{}
é um objeto literal, a suposição padrão é pensar que é simplesmente um bloco vazio inútil.Esta é uma prova desse comportamento:
O código acima mostrará o alerta normalmente e será avaliado como
[true]
, da mesma maneira que{}[true]
é.Declarações de bloco sem ponto e vírgula
Uma instrução do tipo bloco não precisa de um ponto e vírgula após ela.
Por exemplo:
Os dois alertas são mostrados.
Portanto, podemos ver que uma declaração de bloco vazio, sem ponto e vírgula, é válida e simplesmente não faz nada. Dessa forma, quando você entra
{}[true]
no console das Ferramentas do desenvolvedor (ou Firebug), o valor avaliado será o valor da última declaração de expressão . Neste caso, a última declaração expressão é[true]
.2) Em um contexto de atribuição, o analisador garantirá que
{}
seja um objeto literal. Ao fazer var a ={}[true]
, você remove qualquer ambiguidade e informa o analisador que{}
não é uma instrução de bloco.Então, aqui, você está tentando obter um valor com uma chave
"true"
de um objeto vazio. Obviamente, não há par de valores-chave com esse nome de chave. Dessa forma, a variável a é indefinida.Palavras reservadas como chaves de objeto
O ECMAScript 5 permite que as chaves do objeto sejam palavras reservadas. Portanto, as seguintes chaves são legais:
3) A mesma explicação do exemplo 1 . Mas ... Se a
{ b: 12345 }
peça é tratada como uma declaração de bloco, qual é o tipo dab: 12345
declaração?... (?????)
É uma declaração de etiqueta , você já a viu antes ... É usada em loops e in
switch
. Aqui estão alguns links interessantes sobre instruções de rótulo: 1 , (2) [ Melhor maneira de interromper loops aninhados em Javascript? , (3) [ Como quebrar loops aninhados em javascript? .NOTA: Apenas tente avaliar isso:
As instruções do rótulo não podem ser separadas pelo operador de vírgula ; você precisará separá-las com um ponto e vírgula. Portanto, isso é válido:
{a: 1; b: 2}
4) Veja as explicações para os exemplos 1 e 3 ...
5) Mais uma vez, estamos
{ b: 12345 }
sendo tratados como um bloco de código e você está tentando acessar uma propriedade de um bloco de código usando a notação de ponto e, obviamente, isso não é permitido, e o analisador lança um"Unexpected token :"
exceção.6) O código é quase idêntico ao exemplo acima, mas cercando a
{ b: 12345 }
instrução com o operador de agrupamento de expressões , o analisador saberá que é um objeto. Dessa forma, você poderá acessar o"b"
propriedade normalmente.7) Lembre-se do exemplo 2 , temos uma atribuição aqui, o analisador sabe que
{ b: 12345 }
é um objeto.8) Idêntico ao exemplo acima, mas em vez da notação de ponto, aqui estamos usando a notação de colchete .
9) Eu já disse que essa
"identifier: value"
sintaxe dentro de uma instrução de bloco é um rótulo. Mas você também deve saber que um nome de rótulo não pode ser uma palavra-chave reservada (o oposto dos nomes de propriedades do objeto). Quando tentamos definir um rótulo chamado"true"
, obtivemos aSyntaxError
.10) Mais uma vez, estamos lidando com um objeto. Não há problemas ao usar palavras reservadas aqui. =)
11) Finalmente, temos o seguinte:
!{}[true]
Vamos separar as coisas aqui:
a) Ao fazer uma negação, informamos ao analisador que
{}
é um objeto .b) Como mostrado no exemplo 2 , um
{}
objeto não possui uma propriedade chamadatrue
, portanto, essa expressão será avaliada comoundefined
.c) O resultado final é a negação de
undefined
valor. Javascript realiza conversão de tipo implícito , e oundefined
valor é falso .d) Então, a negação de
false
é ...true
!fonte