ぶれすとつーる

だいたいjavascript

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が別の参照になってうまく削除できない みたいなバグを起こします。

っていうか起こしてるコードと出会いました。

なのでご用心を。