Enquanto [] + []
é uma string vazia, [] + {}
é "[object Object]"
e {} + []
é 0
. Por que {} + {}
NaN?
> {} + {}
NaN
Minha pergunta não é por que ({} + {}).toString()
é "[object Object][object Object]"
enquanto NaN.toString()
é "NaN"
, esta parte já tem uma resposta aqui .
Minha pergunta é por que isso acontece apenas no lado do cliente? No lado do servidor ( Node.js ) {} + {}
é "[object Object][object Object]"
.
> {} + {}
'[object Object][object Object]'
Resumindo :
No lado do cliente:
[] + [] // Returns ""
[] + {} // Returns "[object Object]"
{} + [] // Returns 0
{} + {} // Returns NaN
NaN.toString() // Returns "NaN"
({} + {}).toString() // Returns "[object Object][object Object]"
var a = {} + {}; // 'a' will be "[object Object][object Object]"
No Node.js:
[] + [] // Returns "" (like on the client)
[] + {} // Returns "[object Object]" (like on the client)
{} + [] // Returns "[object Object]" (not like on the client)
{} + {} // Returns "[object Object][object Object]" (not like on the client)
javascript
node.js
eval
google-chrome-devtools
web-developer-toolbar
Ionică Bizău
fonte
fonte
{}
pode ser interpretado como uma expressão ou como um objeto primitivo, dependendo do contexto. Talvez o código seja o mesmo no cliente e no servidor, mas esteja interpretando de maneira{}
diferente devido ao contexto diferente da inserção do código.Respostas:
Nota atualizada: isso foi corrigido no Chrome 49 .
Pergunta muito interessante! Vamos cavar.
A causa raiz
A raiz da diferença está na maneira como o Node.js avalia essas instruções em comparação com o desempenho das ferramentas de desenvolvimento do Chrome.
O que o Node.js faz
O Node.js usa o módulo de substituição para isso.
Desde o Node.js código fonte REPL :
Isso funciona como a execução
({}+{})
nas ferramentas de desenvolvedor do Chrome, que também produzem"[object Object][object Object]"
como você esperaria.O que as ferramentas de desenvolvedor do Chrome fazem
Por outro lado, as ferramentas do Chrome Dveloper fazem o seguinte :
Então, basicamente, ele executa um
call
no objeto com a expressão A expressão sendo:Portanto, como você pode ver, a expressão está sendo avaliada diretamente, sem o parêntese de quebra automática.
Por que o Node.js age de maneira diferente
A fonte do Node.js justifica isso:
O nó nem sempre agia assim. Aqui está o commit real que o mudou . Ryan deixou o seguinte comentário sobre a alteração: "Melhore como os comandos REPL são avaliados" com um exemplo da diferença.
Rinoceronte
Atualização - O OP estava interessado em como o Rhino se comporta (e por que ele se comporta como os devtools do Chrome e diferente dos nodejs).
O Rhino usa um mecanismo JS completamente diferente das ferramentas de desenvolvedor do Chrome e do REPL do Node.js., que usam a V8.
Aqui está a linha de tubulação básica do que acontece quando você avalia um comando JavaScript com o Rhino no shell do Rhino.
O shell é executado
org.mozilla.javascript.tools.shell.main
.Por sua vez, chama isso
new IProxy(IProxy.EVAL_INLINE_SCRIPT);
por exemplo, se o código foi passado diretamente com a opção embutida -e.Isso atinge o
run
método do IProxy .Invoca
evalInlineScript
( src ). Isso simplesmente compila a string e a avalia.Basicamente:
Dos três, a concha do Rhino é a que mais se aproxima de um real,
eval
sem qualquer acondicionamento. O Rhino's é o mais próximo de umaeval()
afirmação real e você pode esperar que ela se comporte exatamente comoeval
faria.fonte
eval
)evaluateOn
. No nó, tudo está muito bem documentado - eles têm um módulo REPL dedicado com toda a história agradável e aconchegante no git, tendo usado REPLs antes em meus próprios programas, eu sabia onde procurar :) Estou feliz que você tenha gostado e encontrado útil, mas devo isso à minha familiaridade com essas bases de código (dev-tools e nodejs), e não ao meu intelecto. Ir direto à fonte geralmente é sempre o mais fácil.