Tại sao gọi một hàm trong Node.js REPL bằng) (hoạt động?


191

Tại sao có thể gọi hàm trong JavaScript như thế này, được thử nghiệm với node.js:

~$ node
> function hi() { console.log("Hello, World!"); };
undefined
> hi
[Function: hi]
> hi()
Hello, World!
undefined
> hi)( // WTF?
Hello, World!
undefined
>

Tại sao cuộc gọi cuối cùng hi)(, làm việc? Đây có phải là lỗi trong node.js, lỗi trong công cụ V8, hành vi không được xác định chính thức hoặc JavaScript thực sự hợp lệ cho tất cả các trình thông dịch không?


1
có thể sao chép trong nodejs v0.6.19 trên Ubuntu 13.04
mvp

1
một thử nghiệm nhanh trên jsfiddle.net sẽ cho bạn thấy rằng đó là JavaScript không hợp lệ.
Barshe

6
Có vẻ là một lỗi REPL, đặt hai dòng vào .jssẽ gây ra lỗi cú pháp
leesei

8
Btw, tín dụng đến hạn, điều này đã xuất hiện tại irc (FreeNode #nodejs), bởi @miniml
hyde

3
Perl có một cái gì đó tương tự cho nhiều lý do tương tự : perl -ne '$x += $_; }{ print $x'. Xem các tính năng ẩn của Perl
Adrian Pronk

Câu trả lời:


84

Có vẻ là một lỗi REPL, đặt hai dòng này vào .jssẽ gây ra lỗi cú pháp.

function hi() { console.log("Hello, World!"); }
hi)(

Lỗi:

SyntaxError: Unexpected token )
    at Module._compile (module.js:439:25)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:901:3

Vấn đề được gửi # 6634 .

Đã sao chép vào v0.10.20.


v0.11.7 có cái này cố định.

$ nvm run 0.11.7
Running node v0.11.7
> function hi() { console.log("Hello, World!"); }
undefined
>  hi)(
SyntaxError: Unexpected token )
    at Object.exports.createScript (vm.js:44:10)
    at REPLServer.defaultEval (repl.js:117:23)
    at REPLServer.b [as eval] (domain.js:251:18)
    at Interface.<anonymous> (repl.js:277:12)
    at Interface.EventEmitter.emit (events.js:103:17)
    at Interface._onLine (readline.js:194:10)
    at Interface._line (readline.js:523:8)
    at Interface._ttyWrite (readline.js:798:14)
    at ReadStream.onkeypress (readline.js:98:10)
    at ReadStream.EventEmitter.emit (events.js:106:17)
> 

27
Họ thực sự đã đi trước và sửa nó? Thật đáng tiếc, tôi thực sự muốn thấy nó bắt đầu một nền văn hóa và trở thành một tính năng trong tất cả các ngôn ngữ. Đã bao nhiêu lần tôi gõ) (thay vì () vội vàng ... :))
geomagas

18
@geomagas Bạn nghĩ function a)arg1, arg2( } ]arg2 + arg1[ return; {nên là cú pháp hợp lệ?
azz

40
Không thật sự lắm. Thật ra, đó là một trò đùa.
geomagas

7
Ngày xửa ngày xưa, có một triển khai Lisp với tùy chọn DWIM tự động sửa lỗi chính tả và các lỗi nhỏ khác. vi.wikipedia.org/wiki/DWIM
Barmar

2
@geomagas, tốt, một số người đã đi trước và nghĩ về nó - npmđã install isntall . đặt cược bạn không nhận thấy :)
Eliran Malka

201

Đó là do cách REPL đánh giá đầu vào, cuối cùng là:

(hi)()

Dấu ngoặc bổ sung được thêm vào để buộc nó là Biểu thức :

  // First we attempt to eval as expression with parens.
  // This catches '{a : 1}' properly.
  self.eval('(' + evalCmd + ')',
      // ...

Mục đích là để coi {...}như là Objectchữ / người khởi tạo chứ không phải là một khối .

var stmt = '{ "foo": "bar" }';
var expr = '(' + stmt + ')';

console.log(eval(expr)); // Object {foo: "bar"}
console.log(eval(stmt)); // SyntaxError: Unexpected token :

Và, như leesei đã đề cập, điều này đã được thay đổi cho 0.11.x, nó sẽ chỉ bao bọc{ ... } chứ không phải tất cả đầu vào:

  if (/^\s*\{/.test(evalCmd) && /\}\s*$/.test(evalCmd)) {
    // It's confusing for `{ a : 1 }` to be interpreted as a block
    // statement rather than an object literal.  So, we first try
    // to wrap it in parentheses, so that it will be interpreted as
    // an expression.
    evalCmd = '(' + evalCmd + ')\n';
  } else {
    // otherwise we just append a \n so that it will be either
    // terminated, or continued onto the next expression if it's an
    // unexpected end of input.
    evalCmd = evalCmd + '\n';
  }

19
Điều đó có nghĩa là hi)(argsẽ làm việc? Điều đó có thể bị lạm dụng để viết một số mã thực sự WTF ;-)
Bác sĩ Jones

Tôi vẫn không hiểu tại sao điều đó sẽ chạy. Nó sẽ không gây ra lỗi cú pháp vì paren mở chưa từng có?
Peter Olson

2
hi)(argtrở thành (hi)(arg)- không có gì sánh được
SheetJS

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.