[解決済み] なぜ{}なのですか?+ {}がNaNになるのはクライアント側だけですか?なぜNode.jsではダメなのか?
質問
一方
[] + []
は空文字列です。
[] + {}
は
"[object Object]"
であり、かつ
{} + []
は
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は を複製します。 モジュールを使います。
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]"
が表示されます。
クロームデベロッパーツールでできること
一方 クロームデベロッパーツールでは以下のことができます。 :
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は常にこのように動作するわけではありませんでした。ここでは を変更した実際のコミットです。 . Ryan はこの変更に対して次のコメントを残しています: "REPLコマンドが評価される方法を改善する" その違いの例もあります。
Rhino
更新 - OP が興味を持ったのは Rhino がどのように動作するのか(そして、なぜChromeの開発ツールと同じように動作し、nodejsと違うのか)に興味を持ちました。
Rhinoは、V8を使用しているChromeの開発者ツールやNode.jsのREPLとは異なり、完全に異なるJSエンジンを使用しています。
RhinoのシェルでJavaScriptのコマンドを評価するときの基本的なパイプラインは以下のとおりです。
-
シェルが実行する
org.mozilla.javascript.tools.shell.main
. -
順番に、それは この
new IProxy(IProxy.EVAL_INLINE_SCRIPT);
例えば、インラインスイッチ -e で直接渡された場合。 -
これは IProxy の
run
メソッドに当たります。 -
を呼び出します。
evalInlineScript
( src ). これは単に文字列をコンパイルして、それを評価するものです。
基本的には
Script script = cx.compileString(scriptText, "<command>", 1, null);
if (script != null) {
script.exec(cx, getShellScope()); // <- just an eval
}
3つのうち、Rhinoのシェルは、実際の
eval
をラップすることなく行うものです。Rhinoのものは実際の
eval()
ステートメントに最も近く、まさに
eval
のような動作を期待できます。
関連
-
[解決済み】Node Version Manager のインストール - nvm コマンドが見つかりません。
-
[解決済み] とは何ですか! (not not)演算子とは何ですか?
-
[解決済み] HTML5のlocalStorageにオブジェクトを格納する方法は?
-
[解決済み] JSONPとは何か、なぜ作られたのか?
-
[解決済み] Node.jsを使うタイミングをどう判断するか?
-
[解決済み] Node.jsのmodule.exportsの目的と使い方を教えてください。
-
[解決済み] JavaScriptで日付の書式設定に関するドキュメントはどこにありますか?
-
[解決済み] JSで文字列が正規表現にマッチするかどうかをチェックする
-
[解決済み] クライアントサイドとサーバーサイドのプログラミングの違いは何ですか?
-
[解決済み] Node.js上のクライアント。Uncaught ReferenceError: require は定義されていません。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
JavaScriptの関数この指摘の問題を説明
-
親子コンポーネント通信を解決する3つのVueスロット
-
要素ツリー制御によるvueTreeテーブル
-
[解決済み] Error : 未定義のプロパティ 'map' を読み取ることができません。
-
[解決済み】Node Version Manager のインストール - nvm コマンドが見つかりません。
-
[解決済み】「X-Frame-Options」を「SAMEORIGIN」に設定したため、フレームでの表示を拒否された。
-
[解決済み】 Uncaught TypeError : undefined のプロパティ 'replace' を読み取れない In Grid
-
[解決済み] CodeMash 2012の'Wat'トークで言及された、この奇妙なJavaScriptの動作の説明とは?
-
[解決済み] Chromeのコンソールで{} + {}がNaNでなくなったのはなぜですか?
-
[解決済み] なぜJavaScriptでは!{}[true]がtrueに評価されるのですか?