Stackの実装とイベント設定サンプルコード
動的生成版と関数定義版2つのスタイルで実装してみた。
動的生成版のほうがJavaScriptっぽい。
しかしwindow.onloadの定義がぶくぶくと太っていくのが、気になる。
関数定義版のほうが関数一つ一つは小さくて見通しが良い。
しかしグローバル空間を汚さないように、全体を匿名関数で囲んでいるため、
結局ネストの深さとしては余り差がないかな。
html.js 動的生成版
'use strict'; // Stack サンプル // 画面固有コード // 画面ロードイベント登録 window.addEventListener('load', function() { var i, length; var stack = []; // Stackテーブル // エレメントを取得 var slctStack = document.getElementById('slctStack'); var btnPush = document.getElementById('btnPush'); var btnPop = document.getElementById('btnPop'); var txtPush = document.getElementById('txtPush'); var txtPop = document.getElementById('txtPop'); var pDump = document.getElementById('pDump'); // セレクトボックスオプション数だけ、Stack生成 length = slctStack.length; for (i = 0; i < length; i++) { stack[i] = new Stack.Stack(); } // セレクトボックスのonchangeイベント登録 slctStack.addEventListener('change', function (evt) { // pタグに対してスタックダンプ pDump.innerHTML = stack[slctStack.selectedIndex].Dump(); // txtPush, txtPopクリア txtPush.value = ''; txtPop.value = ''; }, false); // Pushボタンのonclickイベント登録 btnPush.addEventListener('click', function (evt) { // txtPushの値取得 var value = txtPush.value; // セレクトボックス選択インデックス取得 i = slctStack.selectedIndex; if (value) { // 操作対象スタックにプッシュ stack[i].Push(txtPush.value); // txtPushにfocusして選択状態にする。 txtPush.focus(); txtPush.select(); // pタグに対してスタックダンプ pDump.innerHTML = stack[i].Dump(); } }, false); // Popボタンのonclickイベント登録 btnPop.addEventListener('click', function (evt) { // セレクトボックス選択インデックス取得 i = slctStack.selectedIndex; // 操作対象スタックからポップして、txtPopに設定 if (txtPop.value = stack[i].Pop()) { // pタグに対してスタックダンプ pDump.innerHTML = stack[i].Dump(); } }, false); }, false);
html.js 関数定義版
'use strict'; // Stack サンプル // 画面固有コード // 匿名関数内でクロージャ生成 (function() { var elem = {}; // エレメント保持オブジェクト var stackTbl = []; // Stackテーブル var stack; // 操作対象スタック // 画面ロードイベントハンドラ window.addEventListener('load', init, false); // 画面ロード時初期化 function init(evt) { var i, length; // エレメントを取得 elem.slctStack = document.getElementById('slctStack'); elem.btnPush = document.getElementById('btnPush'); elem.btnPop = document.getElementById('btnPop'); elem.txtPush = document.getElementById('txtPush'); elem.txtPop = document.getElementById('txtPop'); elem.pDump = document.getElementById('pDump'); // セレクトボックスオプション数だけ、Stack生成 length = elem.slctStack.length; for (i = 0; i < length; i++) { stackTbl[i] = new Stack.Stack(); } // 初期の操作対象スタックをセレクトボックス選択中に合わせる stack = stackTbl[elem.slctStack.selectedIndex]; // セレクトボックスのonchangeイベントに登録 elem.slctStack.addEventListener('change', chngSlct, false); // Pushボタンのonclickイベントに登録 elem.btnPush.addEventListener('click', clkPush, false); // Popボタンのonclickイベントに登録 elem.btnPop.addEventListener('click', clkPop, false); } // セレクトボックス変更イベントハンドラ function chngSlct(evt) { // 操作対象スタックをセレクトボックスの // インデックスに対応するものに変更 stack = stackTbl[elem.slctStack.selectedIndex]; // pタグに対してスタックダンプ elem.pDump.innerHTML = stack.Dump(); // txtPush, txtPopクリア elem.txtPush.value = ''; elem.txtPop.value = ''; } // Pushボタンクリックイベントハンドラ function clkPush(evt) { // txtPushの値取得 var value = elem.txtPush.value; if (value) { // 操作対象スタックにプッシュ stack.Push(elem.txtPush.value); // txtPushにfocusして選択状態にする。 elem.txtPush.focus(); elem.txtPush.select(); // pタグに対してスタックダンプ elem.pDump.innerHTML = stack.Dump(); } } // Popボタンクリックイベントハンドラ function clkPop(evt) { // 操作対象スタックからポップして、txtPopに設定 if (elem.txtPop.value = stack.Pop()) { // pタグに対してスタックダンプ elem.pDump.innerHTML = stack.Dump(); } } })(); // 即呼び出し
stack.js
'use strict'; // Stack サンプルコード var Stack; if (Stack) { // Stackは定義済み if (typeof Stack != 'object') { // Stackがobjectではない→正体不明のStack // 例外を投げる。 throw new Error('Stack already exists but not object!'); } } else { // 名前空間オブジェクト生成 Stack = {}; } // 匿名関数内で処理 // Nodeを外部から隠し、Stackのみが操作するため (function() { // ノードコンストラクタ function Node(value) { this.value = value; this.next = null; // ひとまずnullを設定しておく } // Stackコンストラクタ Stack.Stack = function() { this.stack = new Node(null); }; // 引数の値をpushする。 Stack.Stack.prototype.Push = function(value) { var node = new Node(value); // スタックに積む node.next = this.stack.next; this.stack.next = node; }; // stackからpopした値を返す。 Stack.Stack.prototype.Pop = function() { var node = this.stack.next; var rtn; if (node) { // 先頭要素をスタックから切り離す。 this.stack.next = node.next; rtn = node.value; } else { // ノード無しのばあい、nullを返す。 rtn = null; } return rtn; }; // stackをdumpした文字列を返す Stack.Stack.prototype.Dump = function() { var rtn = ''; var node; for (node = this.stack.next; node; node = node.next) { rtn += node.value + '<br />'; } return rtn; }; })(); // 即呼び出し
stack.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="Content-Script-Type" content="text/javascript"> <title>Stack Sample</title> <!-- Stackモジュールロード --> <script src="./stack.js"></script> <!-- html依存コード定義 --> <script src="./html.js"></script> </head> <body> <!-- スタックセレクタ --> <select id="slctStack"> <option>stack0</option> <option>stack1</option> <option>stack2</option> </select><br> <!-- 入力ボックス Pushボタン --> <input type="text" id="txtPush"> <button id="btnPush">Push</button><br> <!-- 出力ボックス Popボタン --> <input type="text" id="txtPop" readonly> <button id="btnPop">Pop</button> <!-- Stack Dump用カンバス --> <p id="pDump">Stack Dump</p> </body> </html>