反省点

作成日 : 1999-12-05
最終更新日 :

反省点をあげる。

var 宣言忘れ

まず、var 宣言をしなかったために、変数の名前空間が確保できず、 大変なことになってしまった。 var 宣言をしなくても変数が使えるというのは確かにその通りなのだが、var宣言は その関数のブロック内で有効になる、という意味が込められていることをつい最近(1999-12-05 のとき)知った。 これは、継子立てのところで学んだ経験である。

さらに、var 宣言のみではなく、const 宣言や let 宣言も使える。 これらを積極的に活用すれば、誤りが減るのではないかと思う。(2020-03-09)

+ 演算子の結果予測

それから、+演算子が文字列の連結になってしまう場面が予測できなかったこと。 予測できないと思いがけないエラーになる。 たとえば、k = i + j; とある文があり、i = 1, j = 2 ならば k = 3 を期待する。 ところがこの計算を行ってみたら k = 12 となってしまった。この理由がわからず、悩んだ。 12 としても数字としての意味があるのが落とし穴だ。 種を明かせば、i も j も文字列であったために、+ 演算子は文字列連結として働いてしまった、というのが答だ。 1999 年現在は、怪しいところはみな eval()をつけることにしていた。

2020 年に振り返ると、eval() にはセキュリティが保てなくなる問題や処理時間が長くなるという問題がある。 + 演算子で予期せぬ結果が出てしまうことがないようにするには、オブジェクトの種類を明らかにするようにすべきだろう。 特に、Web から入力された場合では、parseInt や parseFloat などを明示的に使って、 フィールドから得られた文字列を逐次数値に変換するなどの方法が必要だ。 もっといえば、TypeScript のような、より型の厳しい言語を使うしかないのだろう。(2020-03-09)

正規表現

正規表現は面白い。使い方の一つを示す。 JavaScript は機種に依存しない書き方ができるはずなのだが、実際には機種依存性がある。 端的には、改行コードの違いとなって現れる。

詳しくは、古籏さんらの「大全」の本に譲るが、UNIXとMacとDOSとすべてで、改行コードが異なる。 これらを吸収すべく、正規表現を使った。なかなか便利だ。 ソースは前の「回帰分析」の章に載せているので御覧いただければ幸いだ。 "\r\n"から"\r"のみか"\n"のみかをマッチングメソッドによって判定する。 マッチングした改行コードは保存しておき、出力として複数行が必要ならば、 joinメソッドの引数に保存した改行コードを指定すればすむ。

もう一つは、一行にある、空白またはタブで区切られた項目の分割だ。 /[ \t]+/というコードを覚えただけで、世界が明るくなった。 また、正規表現は、特定のメソッドしか使えない、ということではないこともわかった。 実際に私は match メソッドと replace メソッドにしか使えないと思っていたが、 split メソッドにもこの正規表現が使えることがわかった。うれしい。

インラインのイベントハンドラの使用の低減

つい最近まで、ボタンをクリックすると関数 do_xyz によるアクションを起こすという処理を次のように書いてきた。

JavaScript ファイル

// xyz.js
function do_xyz() {
  'use strict';
  alert("do_xyz");
}

HTML ファイル

<script src="xyz.js">
<input type="button" id="xyz" value="実行" onclick="do_xyz()">

インラインのイベントハンドラと呼ばれるこの書き方は、現在では避けるべきものであるとされる。その理由は、 入門 モダン JavaScriptによれば次のとおりである:

現在は、W3C DOM レベル 2 仕様書による addEventListener() メソッドを作成するのが望ましい。 私の場合、実際には前掲書「入門 モダン JavaScript」により定義されたユーティリティを用いて、 間接的に使っている。具体的には、ユーティリティをおさめたファイル utitlities.js により定義された U オブジェクトを使って次のように記す:

JavaScript ファイル

// xyz.js
function do_xyz() {
  'use strict';
  alert("do_xyz");
}
window.onload = function() {
  'use strict';
  U.addEvent(U.$('w3c_dom'), 'click', do_xyz);
}

HTML ファイル

<!-- HTML ファイル -->
<script src="utilities.js">		
<script src="xyz.js">		
<input type="button" id="w3c_dom" value="実行">

下記はユーティリティによるボタンクリックイベントを実装した例である。

document.write() 、document.writeln() の削除

ドキュメントを動的に生成するときに使えるのが、これらのメソッドである。 しかし、これらを濫用することは DOM 表現を乱す。そのため、これらのメソッドの使用は極力控えるべきだ。 代わりの方法として考えられるのが、innerHTML を使う方法である。例えば、書き換え前は次の通りだったとする。

HTML ファイル

...
<script>document.writeln('<p>HTML 文</p>')</script>
...

これを書き直すと次のようになる。HTML ファイルに id をもつブロックが挿入されていることと、 innerHTML を window.onload 内で呼び出すことに注意する。

JavaScript ファイル

// write.js
window.onload = (event) => {
    'use strict';
    let s = '<p>HTML 文</p>';
    document.getElementById('sentence').innerHTML = s;
};

HTML ファイル

<script src="write.js"></script>
...
<div id="sentence"></div>
...

window.onload 内で呼び出さないと、読みだすべき id を含む DOM がすべて読み取れていることの保証ができない。

オブジェクト化の徹底

最後の反省点は、まったくオブジェクト化がなされていないということだ。C++でいうクラスを作る作業は、 C++よりずっと簡単にできる。それなのに、必要な分析と実装をさぼっているのが現実である。

まりんきょ学問所JavaScript 手習い > 反省点


MARUYAMA Satosi