Node.js REPLの関数を)(で呼び出すのはなぜですか?


191

node.jsでテストして、次のようにJavaScriptで関数を呼び出すことができるのはなぜですか。

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

最後の呼び出しが機能するのはなぜhi)(ですか?これは、node.jsのバグ、V8エンジンのバグ、正式に定義されていない動作、またはすべてのインタープリターで実際に有効なJavaScriptですか?


1
Ubuntu 13.04のnodejs v0.6.19で再現可能
mvp

1
jsfiddle.netで簡単にテストすると、JavaScriptが無効であることがわかります。
クリストフ

6
Node REPLバグのようです。2行をaに入れる.jsと構文エラーが発生します
leesei

8
ところで、それが期日であるクレジット、これは@minimlによってirc(FreeNode #nodejs)で登場しました
hyde

3
Perlも同じ理由で似ていますperl -ne '$x += $_; }{ print $x'Perlの隠し機能を
Adrian Pronk 2013年

回答:


84

Node REPLバグのようです。これらの2行をaに入れる.jsと、構文エラーが発生します。

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

エラー:

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

問題は#6634を送信しました

v0.10.20で再現。


v0.11.7ではこの問題が修正されています。

$ 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
彼らは実際に進んでそれを修正しましたか?残念、私は本当にそれが文化を開始し、すべての言語の機能になることを望んでいます。急いで)(の代わりに()の代わりに)(...)を何回入力したか
geomagas 2013年

18
@geomagas function a)arg1, arg2( } ]arg2 + arg1[ return; {有効な構文であるべきだと思いますか?
azz 2013年

40
いいえ、そうではありません。実際、それは冗談でした。
geomagas 2013年

7
むかしむかし、スペルミスやその他の小さなエラーを自動的に修正するDWIMオプションを備えたLisp実装がありました。en.wikipedia.org/wiki/DWIM
Barmar

2
@geomagas、まあ、いくつかはすでに進んでそれについて考えました- npm持っているinstall isntall。あなたは気づいていないに
違い

201

これは、REPLが入力を評価する方法によるもので、最終的には次のようになります。

(hi)()

追加の括弧が追加され、になります

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

その意図は、ブロックとしてではなく、リテラル/ 初期化子{...}として扱うことです。Object

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

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

そして、leeseiが述べたように、これは0.11.xのために変更されました、それ{ ... }すべての入力ではなく単にラップします:

  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
それhi)(argはうまくいくという意味ですか?本当にWTFに覆われたコードを書くために悪用される可能性があります;-)
Doctor Jones

それがなぜ実行されるのか、私にはまだわかりません。開いた括弧が一致していないため、構文エラーが発生しませんか?
Peter Olson

2
hi)(argになる(hi)(arg)-比類のないものは何もない
SheetJS

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.