ただのブログです

技術的な物とかを主に。主にWeb系がメイン。いつか、職業エンジニアになりたい。

抜き打ちテストが分からなかった

抜き打ちテストが分からなかった

(※ブログの存在忘れててgistに書いてしまった)

じゃあ this の抜き打ちテストやるぞーをやってみた。
結果として、コードが読めなくて2問空欄解答をするしかなかったので調べてみました。

あ、やってない人は読む前に先にやってみてください。
ちなみにthisの話はあんまりしません。
そして今日調べたばかりなので間違っている可能性や、そもそも自分の知識不足のせいでバカ発見されただけかも知れません。

ただのindirect eval

問題のコードはこれ(※どうやら改訂されてるようです)

('hoge', eval)('this') === window

正直、このコード見たとき何が起こってるのか理解できなかった。
実行結果じゃなくて、この構文が。

結論から言うとカンマ演算子なのだけど、jsでこの記法を見たことがなかったのでちょっと感動しました。

カンマ演算子とは、MDNに在るとおりforなんかでやる。

for (var i = 0, j = 0; i < 10; i++, j++) {
    console.log(i);
    console.log(j);
} 

の,です。 こう見ると、何それ当たり前の構文じゃん。って感じですが…

var a = (1, "foo");  // a === "foo"

ということができます。

つまりカンマ演算子の挙動としては、

ということです。 Cと同じなんですが、javaC#ではなくなっていたので、まさか(失礼)javascriptにはいたとは…

つまり、

('hoge', eval)('this') === window

(1, eval)('this') === window
(1 == 2, "foo", eval)('this') === window
("Foo".toLocaleLowerCase(), eval)('this') === window

と実質的に同じ挙動を示します。(評価されるので、++iとかしたら違いますが)

結論としてはただのindirect evalされただけのコードだったってことみたいです。

なので、eval絡みだと大体こんな感じ

var a = "global";
(function() {
    var a = "function";
    console.log(a)  // function
    eval("console.log(a)"); // function
    (eval)("console.log(a)");   // function
    console.log("ここからglobal");
    var e = eval;e("console.log(a)");   // global
    var e2;(e2 = eval)("console.log(a)");   // global
    ((function(){return eval})())("console.log(a)");  // global
    ('hoge',eval)("console.log(a)");   // global
})()

eval以外でこういった記法が役に立つケースあるのかな…?

{1, "foo"}の謎現象

ちなみにカンマ演算子に気づくまでに疑問に思ってやったところ、FirebugChromeデバッガーコンソール、Opera Dragonfly上では、自分では理解できない現象が起きました。(IEは無いので調べてません。)
知っている人がいれば、どの辺の言語仕様を見ればいいのか教えてください。

{1, "foo"} // "foo"
var a = {1, "foo"} // もちろんシンタックスエラー
({1, "foo"}) // シンタックスエラー
{1, "foo"} // "foo"

はなぜそう動く…?