更新されたメモ:これは 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 開発者ツールの機能
一方、Chrome 開発者ツールは次のことを行います。
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
、式を使用してオブジェクトに対して a を実行します。式は次のとおりです。
with ((window && window.console && window.console._commandLineAPI) || {}) {
{}+{};// <-- This is your code
}
ご覧のとおり、式は括弧なしで直接評価されています。
Node.js の動作が異なる理由
Node.js のソースはこれを正当化します。
// This catches '{a : 1}' properly.
ノードは常にこのように動作するとは限りませんでした。それを変更した実際のコミットは次のとおりです。Ryan はこの変更について次のコメントを残しました: 「REPL コマンドの評価方法を改善する」と、違いの例を示します。
ライノ
更新 - OP は、 Rhinoがどのように動作するか (そしてなぜそれが Chrome devtools のように動作し、nodejs とは異なるのか) に興味を持っていました。
Rhino は、どちらも V8 を使用する Chrome 開発者ツールや Node.js の REPL とは異なり、まったく異なる JS エンジンを使用します。
以下は、Rhino シェルで Rhino を使用して JavaScript コマンドを評価するときに発生する基本的なパイプラインです。
基本的:
Script script = cx.compileString(scriptText, "<command>", 1, null);
if (script != null) {
script.exec(cx, getShellScope()); // <- just an eval
}
3 つのうち、Rhino のシェルは、eval
ラッピングなしで実際のシェルに最も近いものです。Rhino のステートメントは実際のステートメントに最も近く、実際のeval()
ステートメントとまったく同じように動作することが期待できますeval
。