ieの関数オブジェクトのスコープのきもちわるいやつ、もっときもちわるかった。
javascript gardenとかで紹介されてるこういうスコープ
http://bonsaiden.github.com/JavaScript-Garden/ja/#function.general
[名前付き関数式]のところ
var foo = function bar() { console.log(bar); // 動作する console.log(foo); // 動作する } console.log(bar); // ReferenceError foo(); // 動作する
割と知られてる話だけどfooとbarでは指してる関数オブジェクトは同じですけどスコープが違います。
これはいつものことながらieでは挙動が違います。
in ie
var foo = function bar() { console.log(bar); // 動作する console.log(foo); // 動作する } console.log(bar); // 動作する foo(); // 動作する
とまぁ本来なら外のスコープに露出しないはずのbarが漏れてます。
これだけならかわいいんだけど、とあるコードのパッチ書いてたらもっと気持ち悪いの発見した。
var foo = function bar() { console.log(foo === bar); // true (but ie<9 is false) } foo(); // 動作する
fxとかだとfooとbarは参照も含めて等価なんだけどこれをIEで実行するとfalseと。
これは結構はまりどころが多くて、jqueryのbindやoneとかみたいなのを実装しようとしたときに
fn.bind = ... fn.unbind = ... fn.one = function (eventName, handler) { var that = this; this.bind(eventName, function foo() { handler(); // 一回実行したらunbindする that.unbind(eventName, foo); }); }
とか書いた際に one の中でbindに委譲する際に渡されてる関数オブジェクトと その中でunbindするときに渡してるfooが別の参照になってうまく削除できない みたいなバグを起こします。
っていうか起こしてるコードと出会いました。
なのでご用心を。