久々のエントリーです。
最近はまったく忙しくて、全然勉強する時間もありゃしません。
弊社の人が作ったJavaScriptでトグル処理をするソースコードがメールで流れてきて それに触発されて、自分もいろいろ書いてみて、社内でシェアしたものをうpします。
まるごとJavaScriptを見ていて、クロージャっていいよね。という気分だったので クロージャをおさらいしてみました。 トグル処理の様々な実装方法テスト in JavaScript
最終的なソースコードはこんな感じになったよ。
[js]
/** * オブジェクトを継承する(Objectを汚染拡張 from prototype.js) * @param destination 拡張されるオブジェクト * @param source 雛形オブジェクト */ Object.mixin = function( destination, source ){ for (property in source) destination[property] = source[property]; return destination; }
/** * トグル可能な要素を表すクラス */ var TogglableElement = function(){}; TogglableElement.prototype = { flag:true, resultTarget:undefined, toggle:function(){ this.flag = !this.flag; }, update:function(){ this.resultTarget.innerHTML = ( this.flag ) ? ‘ON’ : ‘OFF’; }, onmouseup:function(){ this.toggle(); this.update(); } };
/** * 初期化 * イベントハンドラはHTML内ではなく、スクリプト内で定義 */ function init(){
/* オブジェクト拡張方式 */ var btn1 = document.getElementById(‘btn1′); var btn2 = document.getElementById(‘btn2′);
// ボタン要素をトグラブルオブジェクトに拡張する Object.mixin( btn1, TogglableElement.prototype ); Object.mixin( btn2, TogglableElement.prototype );
// 出力先を定義する btn1.resultTarget = document.getElementById(‘result1′); btn2.resultTarget = document.getElementById(‘result2′);
/* クロージャ渡し方式 */ document.getElementById(‘btn3′).onmouseup = getToggleClosure( document.getElementById(‘result3′) ); document.getElementById(‘btn4′).onmouseup = getToggleClosure( document.getElementById(‘result4′) );
/* ソースコードの表示トグル */ document.getElementById(‘viewsource-a’).onclick = getToggleClosure2( document.getElementById(‘sourcecode-a’), viewSourceCode ); document.getElementById(‘viewsource-b’).onclick = getToggleClosure2( document.getElementById(‘sourcecode-b’), viewSourceCode ); document.getElementById(‘viewsource-c’).onclick = getToggleClosure2( document.getElementById(‘sourcecode-c’), viewSourceCode ); }
/** * トグル処理&DOM操作のクロージャ関数を返す * 1つの関数を各所で使い回せるようにクロージャ化する * @param target HTMLElement 内容を書き換えるHTML要素 */ function getToggleClosure( target ){ var flag = true; // フラグ。レキシカルスコープ内に保持 var target = target; // ターゲット。レキシカルスコープ内に保持 return function(){ flag = !flag; // フラグを逆転 target.innerHTML = ( flag ) ? ‘ON’ : ‘OFF’; // flag==trueならON }; }
function getToggleClosure2( target, callback ){ var flag = true; var target = target; var callback = callback return function(){ flag = !flag; // フラグを逆転 callback.apply( this, [ target, flag ] ); }; }
function viewSourceCode( target, flag ){ this.innerHTML = ( flag )? ‘ソースコードを表示する’ : ‘ソースコードを隠す’; target.style.display = ( flag )? ‘none’ : ‘block’; }
/** * window.onloadにリスナーを貼る */ if( /msie/.test(navigator.userAgent.toLowerCase()) ) window.attachEvent( ‘onload’, init ); else window.addEventListener( ‘load’, init, true );
[/js]
関連記事