protocol open node manager debug chrome app javascript node.js eval google-chrome-devtools web-developer-toolbar

javascript - open - nodemon inspect



¿Por qué{}+{} es NaN solo en el lado del cliente? ¿Por qué no en Node.js? (1)

Nota actualizada: esto se ha solucionado en Chrome 49 .

Pregunta muy interesante! Vamos a profundizar en.

La causa principal

La raíz de la diferencia radica en cómo Node.js evalúa estas declaraciones en comparación con la forma en que lo hacen las herramientas de desarrollo de Chrome.

Lo que hace Node.js

Node.js usa el módulo repl para esto.

Del código fuente Node.js REPL :

self.eval( ''('' + evalCmd + '')'', self.context, ''repl'', function (e, ret) { if (e && !isSyntaxError(e)) return finish(e); if (typeof ret === ''function'' && /^[/r/n/s]*function/.test(evalCmd) || e) { // Now as statement without parens. self.eval(evalCmd, self.context, ''repl'', finish); } else { finish(null, ret); } } );

Esto funciona igual que correr ({}+{}) en las herramientas de desarrollador de Chrome, que también produce "[object Object][object Object]" como era de esperar.

Qué hacen las herramientas de desarrollo de Chrome

Por otro lado, Chrome dveloper tools hace lo siguiente :

try { if (injectCommandLineAPI && inspectedWindow.console) { inspectedWindow.console._commandLineAPI = new CommandLineAPI(this._commandLineAPIImpl, isEvalOnCallFrame ? object : null); expression = "with ((window && window.console && window.console._commandLineAPI) || {}) {/n" + expression + "/n}"; } var result = evalFunction.call(object, expression); if (objectGroup === "console") this._lastResult = result; return result; } finally { if (injectCommandLineAPI && inspectedWindow.console) delete inspectedWindow.console._commandLineAPI; }

Básicamente, realiza una call al objeto con la expresión. La expresión es:

with ((window && window.console && window.console._commandLineAPI) || {}) { {}+{};// <-- This is your code }

Entonces, como puede ver, la expresión se está evaluando directamente, sin el paréntesis de ajuste.

Por qué Node.js actúa de manera diferente

La fuente de Node.js justifica esto:

// This catches ''{a : 1}'' properly.

Nodo no siempre actuó así. Aquí está el compromiso real que lo cambió . Ryan dejó el siguiente comentario sobre el cambio: "Mejora cómo se evaden los comandos REPL" con un ejemplo de la diferencia.

Rinoceronte

Actualización: OP estaba interesado en cómo se comporta Rhino (y por qué se comporta como los devtools de Chrome y a diferencia de nodejs).

Rhino usa un motor JS completamente diferente a diferencia de las herramientas de desarrollo de Chrome y REPL de Node.js, que usan V8.

Aquí está la línea básica de lo que sucede cuando evalúa un comando de JavaScript con Rhino en el shell de Rhino.

  • El shell ejecuta org.mozilla.javascript.tools.shell.main .

  • A su vez, llama a this new IProxy(IProxy.EVAL_INLINE_SCRIPT); por ejemplo, si el código se pasó directamente con el interruptor en línea -e.

  • Esto golpea el método de run de IProxy.

  • Invoca evalInlineScript ( src ). Esto simplemente compila la cadena y la evalúa.

Básicamente:

Script script = cx.compileString(scriptText, "<command>", 1, null); if (script != null) { script.exec(cx, getShellScope()); // <- just an eval }

De los tres, el caparazón de Rhino es el que hace lo más parecido a una eval real sin ningún ajuste. Rhino''s es lo más cercano a una declaración eval() real y puedes esperar que se comporte exactamente como lo haría eval .

Mientras que [] + [] es una cadena vacía, [] + {} es "[object Object]" , y {} + [] es 0 . ¿Por qué es {} + {} NaN?

> {} + {} NaN

Mi pregunta no es por qué ({} + {}).toString() es "[object Object][object Object]" mientras NaN.toString() es "NaN" , esta parte ya tiene una respuesta .

Mi pregunta es: ¿por qué sucede esto solo en el lado del cliente? En el lado del servidor ( Node.js ) {} + {} es "[object Object][object Object]" .

> {} + {} ''[object Object][object Object]''

Resumiendo :

En el lado del 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]"

En 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)