While [] + []
est une chaîne vide, [] + {}
est "[object Object]"
et {} + []
est 0
. Pourquoi {} + {}
NaN?
> {} + {}
NaN
Ma question est pourquoi ({} + {}).toString()
est "[object Object][object Object]"
tout NaN.toString()
est "NaN"
, cette partie a une réponse déjà ici .
Ma question est pourquoi cela se produit uniquement du côté client? Du côté du serveur ( Node.js ) {} + {}
est "[object Object][object Object]"
.
> {} + {}
'[object Object][object Object]'
En résumé :
Côté client:
[] + [] // 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]"
Dans 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)
{}
peut être interprété comme une expression ou comme une primitive d'objet selon le contexte. Peut-être que le code est le même sur le client et sur le serveur, mais il est interprété{}
différemment en raison du contexte différent de la saisie du code.Réponses:
Remarque mise à jour: cela a été corrigé dans Chrome 49 .
Question très intéressante! Allons creuser.
La cause-racine
La racine de la différence réside dans la façon dont Node.js évalue ces déclarations par rapport à la façon dont les outils de développement Chrome le font.
Ce que fait Node.js
Node.js utilise le module repl pour cela.
À partir du code source Node.js REPL :
Cela fonctionne comme si vous
({}+{})
exécutiez les outils de développement Chrome, qui produisent également"[object Object][object Object]"
comme vous vous y attendez.Que font les outils de développement Chrome
D'autre part, les outils de développement Chrome effectuent les opérations suivantes :
Donc, fondamentalement, il effectue un
call
sur l'objet avec l'expression. L'expression étant:Ainsi, comme vous pouvez le voir, l'expression est évaluée directement, sans la parenthèse d'habillage.
Pourquoi Node.js agit différemment
La source de Node.js justifie ceci:
Node n'a pas toujours agi comme ça. Voici le commit réel qui l'a changé . Ryan a laissé le commentaire suivant sur le changement: "Améliorez la façon dont les commandes REPL sont évaluées" avec un exemple de la différence.
Rhinocéros
Mise à jour - OP était intéressé par le comportement de Rhino (et pourquoi il se comporte comme les outils de développement Chrome et contrairement à nodejs).
Rhino utilise un moteur JS complètement différent, contrairement aux outils de développement Chrome et au REPL de Node.js qui utilisent tous deux la V8.
Voici la ligne de conduite de base de ce qui se passe lorsque vous évaluez une commande JavaScript avec Rhino dans le shell Rhino.
Le shell fonctionne
org.mozilla.javascript.tools.shell.main
.À son tour, il appelle cela
new IProxy(IProxy.EVAL_INLINE_SCRIPT);
par exemple, si le code a été transmis directement avec le commutateur en ligne -e.Cela frappe IProxy
run
méthode .Il invoque
evalInlineScript
( src ). Cela compile simplement la chaîne et l'évalue.Fondamentalement:
Sur les trois, la coquille de Rhino est celle qui fait la chose la plus proche d'un réel
eval
sans aucun emballage. Rhino est le plus proche d'uneeval()
déclaration réelle et vous pouvez vous attendre à ce qu'il se comporte exactement comme leeval
ferait.la source
eval
)evaluateOn
. Dans node, tout est très bien documenté - ils ont un module REPL dédié avec toute l'histoire agréable et confortable sur git, ayant utilisé des REPL auparavant sur mes propres programmes, je savais où chercher :) Je suis heureux que vous ayez aimé et trouvé c'est utile, mais je le dois à ma familiarité avec ces bases de code (dev-tools et nodejs) plutôt qu'à mon intellect. Aller directement à la source est souvent toujours le plus simple.