Lưu ý cập nhật: điều này đã được sửa trong Chrome 49 .
Câu hỏi rất thú vị! Nào cùng đào vào bên trong.
Nguyên nhân sâu xa
Căn nguyên của sự khác biệt là cách Node.js đánh giá các tuyên bố này so với cách các công cụ phát triển Chrome thực hiện.
Node.js làm gì
Node.js sử dụng repl mô-đun cho việc này.
Từ mã nguồn REPL của Node.js :
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);
}
}
);
Điều này hoạt động giống như chạy ({}+{})
trong các công cụ dành cho nhà phát triển Chrome, cũng tạo ra "[object Object][object Object]"
như bạn mong đợi.
Các công cụ phát triển chrome làm gì
Mặt khác, các công cụ dveloper của Chrome thực hiện như sau :
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;
}
Về cơ bản, nó thực hiện một call
trên đối tượng với biểu thức. Biểu thức là:
with ((window && window.console && window.console._commandLineAPI) || {}) {
{}+{};// <-- This is your code
}
Vì vậy, như bạn có thể thấy, biểu thức đang được đánh giá trực tiếp, không có dấu ngoặc đơn.
Tại sao Node.js hoạt động khác nhau
Nguồn của Node.js biện minh cho điều này:
// This catches '{a : 1}' properly.
Nút không phải lúc nào cũng hành động như thế này. Đây là cam kết thực tế đã thay đổi nó . Ryan đã để lại bình luận sau đây về sự thay đổi: "Cải thiện cách các lệnh REPL được đánh giá cao" với một ví dụ về sự khác biệt.
Tê giác
Cập nhật - OP quan tâm đến cách Rhino hành xử (và tại sao nó hoạt động như các devtools của Chrome và không giống như nodejs).
Rhino sử dụng một công cụ JS hoàn toàn khác với các công cụ dành cho nhà phát triển Chrome và REPL của Node.js, cả hai đều sử dụng động cơ V8.
Đây là dòng ống cơ bản về những gì xảy ra khi bạn thực hiện lệnh JavaScript với Rhino trong trình bao Rhino.
Về cơ bản:
Script script = cx.compileString(scriptText, "<command>", 1, null);
if (script != null) {
script.exec(cx, getShellScope()); // <- just an eval
}
Trong số ba, vỏ của Rhino là thứ gần giống với thực tế nhất eval
mà không có sự bao bọc nào. Rhino's là gần nhất với một eval()
tuyên bố thực tế và bạn có thể mong đợi nó hoạt động chính xác như eval
sẽ.