wtfjs: I’m certain that this will end all debate about where curly braces belong… right?
function laugh_undefined() { return { haha: "ha!" }; } laugh_undefined(); // returns undefined
function laugh_okey() { return { haha: "ha!" }; } laugh_okey(); // returns Object: { haha: "ha!" }
そんなバカな。期待と違う動作をするではないか。しかも、まともな解説がない。
I’m certain that this will end all debate about where curly braces belong… right?
とあるだけだ。
ここは、私が持っている唯一の能力である、「規格を読む程度の能力」を発揮する時だ。さっそく規格にあたろう。
まず、何が問題なのか。私は、この二つの関数が、全く同じように動作し、どちらも、オブジェクトを返すことを期待している。それなのに、laugh_undefinedの方は、undefinedを返す。これは一体どういう事なのか。
まず、{ haha: "ha!" }というexpressionだが、これは、規格では、Object Initialiserと呼ばれている。これは、改行があろうとなかろうと関係がない。
まてよ、もしかしたら、{}をBlock statementと解釈しているのではあるまいか。規格を調べたところ、果たして、名前通りの、Block statementは存在した。いやしかし、もしこれがBlockと解釈されているのなら、haha: "ha!"、は、文法エラーである。しかし、どのブラウザも、文法エラーを指摘しない。ということは、どちらも、Object Initialiserと解釈されているはずだ。
とにかく、return statementは、もしかしたら、expressionではなく、statementを期待しているのかもしれない。そうであれば、Blockが優先されるはずだ。ブラウザが文法エラーを出さないのは、単に実装の問題なのかもしれない。さっそく、return statementを調べよう。
return [no LineTerminator here] Expressionopt ;
[no LineTerminator here]というものが気になる。これはなんだ。
If the phrase “[no LineTerminator here]” appears in the right-hand side of a production of the syntactic grammar, it indicates that the production is a restricted production: it may not be used if a LineTerminator occurs in the input stream at the indicated position. For example, the production:
ReturnStatement :
return [no LineTerminator here] Expressionopt ;indicates that the production may not be used if a LineTerminator occurs in the program between the return token and the Expression.
なるほど、return statementでは、returnとexpressionの間に、改行があってはならないらしい。いや、mayなので、改行があってもいいのだろう。ただし、expressionを省略したことになるだろうが。
そして、return statementのexpressionが省略された場合は、"If Expression is omitted, the return value is undefined."となるので、undefinedが返される。
ちなみに、セミコロンを省略してもよい理由については、本の虫: Javascriptで改行が特別な意味を持つケースを参照のこと。
JavascriptはC++より難しい。
でも、規格は、C++より読みやすいと思う。すぐに理解できた。
wtfjsに掲載されているコードは、どれも非常に興味深いので、Javascriptプログラマは、ぜひ一読しておくことをおすすめする。
追記:昔、入門用に買ったオライリーを引っ張り出してきたら、return文に改行を書くと、セミコロンが補われるから気をつけろと書いてあった。さすがオライリーだ。しかし、これは重要だ。とすると、およそJavascriptの入門書なら、必ず書いておくべきであり、すべてのJavascriptプログラマは、これを知っているべきである。知らなかったのは、ひょっとして私だけなのだろうか。Javascript、怖い言語だ。
> いや、mayなので、改行があってもいいのだろう。
ReplyDeleteこれはmay notの一部なので、「~してはいけない」という禁止の意だと思います。
> いやしかし、もしこれがBlockと解釈されているのなら、haha: "ha!"、は、文法エラーである。
これは本体が式文であるラベル付き文とみなされるので、文法エラーにはなりません。
>これはmay notの一部なので、「~してはいけない」という禁止の意だと思います。
ReplyDeleteいや、そういう意味ではなくて、may notなので「弱い」禁止なのだろうということです。
shall notとは違うということです。
>これは本体が式文であるラベル付き文とみなされるので、文法エラーにはなりません。
あ、なるほど。
やはりJavascriptは変態だ。