リハビリに手頃な問題だったので。
これ、実は「Java開発者のためのAjax実践開発入門」でも紹介されている書き方。
for 文と無名関数のイディオム - IT戦記というわけで、これをすべて解決するのが
for (var i = 0, len = list.length; i < len; i++) (function(node, i) {
var text = node.textContent;
node.onclick = function() { alert(text) };
})(list[i], i)
なのだ。
ただし、コメント欄に残された問題が残る。
自分でも検証してみた。
n = :
これ、デフォルトでは100万回にしてあるけど、IEで実行する場合は一桁少ない10万が推奨。
Scopeless
var result = 0;
for (var i = 0; i < n; i++){
result = i;
}
Closure as a block
var result = 0;
for (var i = 0; i < n; i++) (function(a){
result = a;
})(i);
with()
var result = 0;
for (var i = 0; i < n; i++) {
with({a:i}) {
result = a;
}
}
どのブラウザーで実行しても、function()しない方が速いのだけど、IEの場合、笑っちゃうほど遅くなってしまう。
で、少し工夫してみる。
Closure as a block, predefined
var result = 0;
for (var i = 0, block = function(a){ result = a }; i < n; i++) block(i);
Closure as an iterator
var result = 0;
(function(block){
for (var i = 0; i < n; i++) block(i);
})(function(a){
result = a
});
いずれの場合も倍以上高速にはなった。IEだとそれでもまだ我慢できないほど遅いけど。
とはいえ、amachangの例ではスコープはどうしても必要になる。
以上をふまえると、
for (var i = 0, len = list.length; i < len; i++) (function(node, i) {
var text = node.textContent;
node.onclick = function() { alert(text) };
})(list[i], i)
は
var block = function(node){
var text = node.textContent;
node.onclick = function() { alert(text) };
};
for (var i = 0, len = list.length; i < len; i++) block(list[i]);
と書くのが現状でのベストプラクティスかと思われ。別の言い方をすると、なるべくループの中ではclosureを生成しない方がよい。
Dan the JavaScripter
このブログにコメントするにはログインが必要です。
さんログアウト
この記事には許可ユーザしかコメントができません。