こんにちは、
クロージャとは
クロージャはその定義を説明されてもなかなか理解できないため、
さて、
では、
function 関数A(){
var 変数a = 'a';
function 関数B(){
var 変数b = 変数a + 'b';
var 関数C = function(){
var 変数c = 変数a + 変数b + 'c';
alert(変数c); // aabc
}
関数C();
}
関数B();
}
関数A();
関数Aの中に関数Bを、
関数Bは関数Aの中に定義された関数
さてさて、
このように、
function 関数A(){
var 変数a = 0;
function 関数B(){
変数a++;
}
関数B();
関数B();
alert(変数a); // 2
}
関数A();
関数A();
こちらは関数Aを2度呼び出しています。一度目の呼び出しでは2がalertされます。また、
function 関数A(){
var 変数a = 0;
function 関数B(){
return ++変数a;
}
return 関数B;
}
var 変数β = 関数A();
alert(変数β()); // 1
alert(変数β()); // 2
var 変数γ = 関数A();
alert(変数γ()); // 1
alert(変数β()); // 3
こちらはクロージャと前回取り上げた高階関数との組み合わせです。関数Aは関数Bを返すようにしたので、
一方で、
このあたりは少々ややこしくなってきましたね。とはいえ、
ここまででクロージャの解説はほぼ終わりです。ここからは実用的なケースを見ていきます。
テーブルのハイライト
ここで、
といっても、
tr:hover{
background-color:#ffffaa;
}
1 | 2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 |
この通り、
では、
window.onload = function(){
var table=document.getElementById('js5-table');
var trs = table.getElementsByTagName('tr');
for (var i = 0, len=trs.length;i < len; i++){
var tr = trs[i];
tr.onmouseover = function(){
tr.className = 'hover';
};
tr.onmouseout = function(){
tr.className = '';
};
}
};
一見上手く動きそうに見えるコードですが、
window.onload = function(){
var table=document.getElementById('js5-table');
var trs = table.getElementsByTagName('tr');
for (var i = 0, len=trs.length;i < len; i++){
var tr = trs[i];
tr.onmouseover = function(){
tr.className = 'hover';
};
tr.onmouseout = function(){
tr.className = '';
};
}
};
この通り、
ではこの問題を解決するにはforループの中、
window.onload=function(){
var table=document.getElementById('js5-table');
var trs = table.getElementsByTagName('tr');
for (var i = 0, len=trs.length;i < len; i++){
var tr = trs[i];
(function(_tr){
_tr.onmouseover = function(){
_tr.className = 'hover';
};
_tr.onmouseout = function(){
_tr.className = '';
};
})(tr);
}
}
このようにforループ内に関数を作り、
クロージャを避ける
さて、
クロージャを避ける方法は単純で、
マウスオーバーで背景色を変える実装
for (var i = 0, len=trs.length;i < len; i++){
var tr = trs[i];
tr.onmouseover = function(){
this.className = 'hover';
};
tr.onmouseout = function(){
this.className = '';
};
}
もしくは、
マウスオーバーで背景色を変える実装
for (var i = 0, len=trs.length;i < len; i++){
mouse_hightlight(trs[i]);
}
}
function mouse_hightlight(tr){
tr.onmouseover = function(){
tr.className = 'hover';
};
tr.onmouseout = function(){
tr.className = '';
};
}
ただし、
このように同じ機能を実現する際に色々と工夫ができるところはプログラミングの面白さでもあります。是非、
最後に、
最適化前は初期化が重く、
最適化の内容は、
まとめ
今回はJavaScriptにおいて重要なクロージャを中心とした関数の扱いを解説しました。次回からはクロスブラウザの最大の難所であるDOMについて紹介しつつ、