JavaScript、クロージャをおさらいしてみる

このエントリーを含むはてなブックマーク

久々のエントリーです。

最近はまったく忙しくて、全然勉強する時間もありゃしません。

弊社の人が作ったJavaScriptでトグル処理をするソースコードがメールで流れてきて それに触発されて、自分もいろいろ書いてみて、社内でシェアしたものをうpします。

まるごとJavaScriptを見ていて、クロージャっていいよね。という気分だったので クロージャをおさらいしてみました。 トグル処理の様々な実装方法テスト in JavaScript

最終的なソースコードはこんな感じになったよ。

  1. /**
  2. * オブジェクトを継承する(Objectを汚染拡張 from prototype.js)
  3. * @param destination 拡張されるオブジェクト
  4. * @param source 雛形オブジェクト
  5. */
  6. Object.mixin = function( destination, source ){
  7.   for (property in source)
  8.     destination[property] = source[property];
  9.   return destination;
  10. }
  11.  
  12. /**
  13. * トグル可能な要素を表すクラス
  14. */
  15. var TogglableElement = function(){};
  16. TogglableElement.prototype = {
  17.   flag:true,
  18.   resultTarget:undefined,
  19.   toggle:function(){
  20.     this.flag = !this.flag;
  21.   },
  22.   update:function(){
  23.     this.resultTarget.innerHTML = ( this.flag ) ? 'ON' : 'OFF';
  24.   },
  25.   onmouseup:function(){
  26.     this.toggle();
  27.     this.update();
  28.   }
  29. };
  30.  
  31. /**
  32. * 初期化
  33. * イベントハンドラはHTML内ではなく、スクリプト内で定義
  34. */
  35. function init(){
  36.  
  37.   /* オブジェクト拡張方式 */
  38.   var btn1 = document.getElementById('btn1');
  39.   var btn2 = document.getElementById('btn2');
  40.  
  41.   //  ボタン要素をトグラブルオブジェクトに拡張する
  42.   Object.mixin( btn1, TogglableElement.prototype );
  43.   Object.mixin( btn2, TogglableElement.prototype );
  44.  
  45.   //  出力先を定義する
  46.   btn1.resultTarget = document.getElementById('result1');
  47.   btn2.resultTarget = document.getElementById('result2');
  48.  
  49.   /* クロージャ渡し方式 */
  50.   document.getElementById('btn3').onmouseup = getToggleClosure( document.getElementById('result3') );
  51.   document.getElementById('btn4').onmouseup = getToggleClosure( document.getElementById('result4') );
  52.  
  53.   /* ソースコードの表示トグル */
  54.   document.getElementById('viewsource-a').onclick = getToggleClosure2( document.getElementById('sourcecode-a'), viewSourceCode );
  55.   document.getElementById('viewsource-b').onclick = getToggleClosure2( document.getElementById('sourcecode-b'), viewSourceCode );
  56.   document.getElementById('viewsource-c').onclick = getToggleClosure2( document.getElementById('sourcecode-c'), viewSourceCode );
  57. }
  58.  
  59. /**
  60. * トグル処理&DOM操作のクロージャ関数を返す
  61. * 1つの関数を各所で使い回せるようにクロージャ化する
  62. * @param target HTMLElement 内容を書き換えるHTML要素
  63. */
  64. function getToggleClosure( target ){
  65.   var flag = true// フラグ。レキシカルスコープ内に保持
  66.   var target = target;  //  ターゲット。レキシカルスコープ内に保持
  67.   return function(){
  68.     flag = !flag;  //  フラグを逆転
  69.     target.innerHTML = ( flag ) ? 'ON' : 'OFF'; // flag==trueならON
  70.   };
  71. }
  72.  
  73. function getToggleClosure2( target, callback ){
  74.   var flag = true;
  75.   var target = target;
  76.   var callback = callback
  77.   return function(){
  78.     flag = !flag;  //  フラグを逆転
  79.     callback.apply( this, [ target, flag ] );
  80.   };
  81. }
  82.  
  83. function viewSourceCode( target, flag ){
  84.   this.innerHTML = ( flag )? 'ソースコードを表示する' : 'ソースコードを隠す';
  85.   target.style.display = ( flag )? 'none' : 'block';
  86. }
  87.  
  88. /**
  89. * window.onloadにリスナーを貼る
  90. */
  91. if( /msie/.test(navigator.userAgent.toLowerCase()) )
  92.   window.attachEvent( 'onload', init );
  93. else
  94.   window.addEventListener( 'load', init, true );


Posted in javascript, programing, 日記 at 3月 16th, 2007. Trackback URI: trackback

No Responses to “JavaScript、クロージャをおさらいしてみる”

Leave a Reply