Hatena::ブログ(Diary)

latest log このページをアンテナに追加 RSSフィード

2011-02-11

IE9RC で document が const になり再定義が不可能になった

IE9RC の挙動を調べています。

IE9RC では @amachang さんの

/*@cc_on var doc = document; eval('var document = doc'); @*/

が封印されてる

http://twitter.com/#!/uupaa/status/35942322231320576

残念ながら、 @amachang さんの発案した方法がIE9で封印されてしまったようです。

IE9RC Release note http://msdn.microsoft.com/en-US/ie/ff468705.aspx

window.document が const になったため、再代入するとエラーになります。

http://jsdo.it/uupaa/Wq0w で試せます。

回避案

(function(document) {
  // ローカルスコープ
  doc.createElement("div");
})(document);

こんな感じにするといいかもしれません。ローカルスコープ内では document にアクセスすると、同じような効果が得られます。

ついでにナビ子記法の導入もおすすめです → http://handsout.jp/slide/1883

ナビ子記法のスライドに書いていない事

あまりメリットを書きすぎると胡散臭いだろうなと思い、スライドには書いてないことがあったりします。

ナビ子記法ならさらに高速化
var lib = {}:
(function(doc) {
  // スコープ内部
  lib.api1 = libapi1; // function
  lib.api2 = libapi2; // function
  lib.api3 = libapi3; // function
})(docuemnt);

スコープ内部では、 lib.api1() として関数を呼び出さずに libapi1() として呼び出すと lib.xxx() 呼び出しに伴うコスト(ドット演算子の名前解決コスト)をカットできます。

ナビ子記法なら、コード圧縮率も向上

さらにコードの圧縮時(Minify)に、lib.api1() といったコードは x.api1() と8文字以下には圧縮できませんが、libapi1() と記述していると x() や xx() のように3〜4文字に圧縮されます。

lib.api1() は圧縮しても、せいぜい x.api1() にしかならない
libapi1() を圧縮すると、 x() や xx() に圧縮される
ナビ子記法ならECMAScriptJScriptの解釈の違いも発生しなくなる

IE6IE8JScriptでは名前付きの匿名関数のスコープの扱いが ECMAScript-262 5th Edition や他のブラウザの実装とは異なるため、JScriptべったりなコードを書くとトラブルが発生する場合があります。

var fn = function fnName() {};

if (typeof fnName === "function") {
    alert( "maybe legacy JScript(IE6, IE7, IE8)" );
    if (fn !== fnName) {
        alert( "??" );
    }
} else {
    alert( "ECMAScript standard" );
}

IE6IE8 において typeof fn は "function" ですが、ECMAScript 準拠であれば typeof fn は "undefined" になります。


ナビ子記法は、一石七鳥ぐらいある気がするけど

あんまりメリットばかりPUSHすると胡散臭くなるから自重モード

おまけ

uupaa.js では、uu.ready からコールバックされた時の第二引数が document オブジェクトなので、

uu.ready(function(uu, doc) {
  alert( doc.documentMode );
});

最初からナビ子記法のメリットをおいしくいただけます。

おまけのおまけ

第一引数には uupaa.js のルートオブジェクト(uu)が渡されるのですが、これを uu ではなく $ で受け取ると、ちょっとしたデジャブ感を楽しむ事ができます。

uu.ready(function($, doc) {
  $(".hoge").click(function() {
    
  });
});

#ちょっとだけですが