LoginSignup
244
237

More than 5 years have passed since last update.

(0, eval)('this')とは何なのか

Last updated at Posted at 2015-07-01

はじめに

knockout.jsの冒頭のソースコードを見たとき気になる1行があった。

knockout.js
    var window = this || (0, eval)('this'), ...

この(0,eval)('this')はいったい何なのか。調べた。

調べた結果

これはindirect eval callを使用した、どのスコープでも必ずグローバルオブジェクトのthisを取得するためのテクニックであった。

ES5ではevalを直接呼び出すと、引数のコードはそのスコープで実行されるが、間接的にevalを呼び出すと、引数のコードは必ずグローバルスコープとなるそうだ。なので引数のthisは必ずグローバルオブジェクトとなる。ブラウザではwindowとなり、Nodeではglobalになるのだ。実際どうするかだが、eval関数を変数に代入し、その変数で実行すればよい。

// Nodeで実行
var obj = new (function(){
    this.direct = eval('this');
    var ev = eval;// 変数に代入
    this.indirect = ev('this');
});

console.log(obj.direct === global);//false
console.log(obj.indirect === global);//true

これを極限にまで簡略化すると(0,eval)('this')となる。カンマ演算子は左から順に評価して、最後の項目を返す。なので(0,eval)はevalを返す関数とみることができる。こういうイメージだろうか。

 (function(){ return eval;}(0))('this');

返す値は一時変数に代入されるので、そこでevalの間接参照となり、グローバルスコープで実行され、グローバルスコープのthisが取得できる。

何なのかわかったところで

実際に試すと見事グローバルスコープのthisが取得できた。

// Nodeで実行
var obj = new (function(){
    this.direct = eval('this');
    this.indirect = (0,eval)('this');
});

console.log(obj.direct === global);//false
console.log(obj.indirect === global);//true

244
237
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
244
237