왜 {} + {}가 클라이언트 측에서만 NaN입니까? Node.js에없는 이유는 무엇입니까?
While [] + []
은 빈 문자열이며 [] + {}
is "[object Object]"
이며 {} + []
is 0
입니다. 왜 {} + {}
NaN입니까?
> {} + {}
NaN
왜 내 질문은 아닌 ({} + {}).toString()
것입니다 "[object Object][object Object]"
동안 NaN.toString()
이다 "NaN"
, 이 부분은 이미 여기에 답이 있습니다 .
내 질문은 왜 이것이 클라이언트 측에서만 발생합니까? 서버 측 ( Node.js ) {} + {}
입니다 "[object Object][object Object]"
.
> {} + {}
'[object Object][object Object]'
요약 :
클라이언트 측에서 :
[] + [] // 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]"
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)
업데이트 된 참고 사항 : 이것은 Chrome 49에서 수정되었습니다 .
매우 흥미로운 질문입니다! 파헤쳐 보자.
근본 원인
차이점은 Node.js가 이러한 문장을 평가하는 방법과 Chrome 개발 도구의 작동 방식에 있습니다.
Node.js의 기능
Node.js는이를 위해 repl 모듈을 사용합니다 .
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);
}
}
);
이것은 ({}+{})
Chrome 개발자 도구에서 실행 되는 것과 똑같이 작동 하며 "[object Object][object Object]"
예상대로 생성 됩니다.
크롬 개발자 도구의 기능
반면 Chrome dveloper 도구는 다음을 수행합니다 .
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;
}
따라서 기본적으로 call
표현식으로 객체를 수행합니다 . 표현은 다음과 같습니다.
with ((window && window.console && window.console._commandLineAPI) || {}) {
{}+{};// <-- This is your code
}
보시다시피, 래핑 괄호없이 표현식이 직접 평가됩니다.
Node.js가 다르게 작동하는 이유
Node.js의 소스는 이것을 정당화합니다.
// This catches '{a : 1}' properly.
Node did not always act like this. Here is the actual commit that changed it. Ryan left the following comment on the change: "Improve how REPL commands are evaled" with an example of the difference.
Rhino
Update - OP was interested in how Rhino behaves (and why it behaves like the Chrome devtools and unlike nodejs).
Rhino uses a completely different JS engine unlike the Chrome developer tools and Node.js's REPL which both use V8.
Here is the basic pipe line of what happens when you eval a JavaScript command with Rhino in the Rhino shell.
The shell runs
org.mozilla.javascript.tools.shell.main
.In turn, it calls this
new IProxy(IProxy.EVAL_INLINE_SCRIPT);
for example, if the code was passed directly with the inline switch -e.This hits IProxy's
run
method.It invokes
evalInlineScript
(src). This simply compiles the string and evals it.
Basically:
Script script = cx.compileString(scriptText, "<command>", 1, null);
if (script != null) {
script.exec(cx, getShellScope()); // <- just an eval
}
Out of the three, Rhino's shell is the one that does the closest thing to an actual eval
without any wrapping. Rhino's is the closest to an actual eval()
statement and you can expect it to behave exactly like eval
would.
참고URL : https://stackoverflow.com/questions/17268468/why-is-nan-only-on-the-client-side-why-not-in-node-js
'development' 카테고리의 다른 글
scanf로 문자열 읽기 (0) | 2020.06.26 |
---|---|
간단한 파이썬 웹 서비스를 만드는 가장 좋은 방법 (0) | 2020.06.26 |
데이터베이스 스키마를 시각화하는 좋은 도구? (0) | 2020.06.26 |
왜 배열이 IList를 구현합니까? (0) | 2020.06.26 |
Hudson / Jenkins 구성 파일을 소스 제어로 유지하는 방법이 있습니까? (0) | 2020.06.26 |