2013年10月4日金曜日

JavaScriptに連想配列(ハッシュテーブル)は存在しない

最近JavaScriptの勉強を兼ねて、仕事(Windowsサーバのシステム)で
JScriptを利用するようにしている。(残念ながらLinux環境にない。。。)
Webで調べながら「JavaScriptでハッシュを実現するにはこうすればいいのね」と
得意げに 以下のようなコードを書いていた。

var hash = {};
hash[ 'apple' ] = 100;
hash[ 'lemon' ] = 200;
for(key in hash){
  var ret = hash[key];
}
retにはそれぞれ100,200が返る。

しかし実はJavaScriptにハッシュなど存在しなかった。
それを知ったのはつい最近のことである。

JavaScriptで配列を実現できるのはArray()だけだ。
Array()による配列の実現は以下のとおりである。
var list = []; //空の配列を生成。 var list = new Array()と同義。
list[0] = 100;
list[1] = 200;
for(var i=0 ; i<list.length ; i++){
  var ret = list[i];
}

じゃあどうして前者のコードはあたかもハッシュテーブルのように
見えるのだろうか?そしてハッシュテーブルとは別物なのか?
var hash = {}; は
var hash = new Object();と同義である。
つまりhashは空の新しいObject型のオブジェクトを生成していることを表す。
 
では以下のコードは何を意味するか?
hash[ 'apple' ] = 100;
これはhashオブジェクトにappleプロパティを設定し、値を100とする
ことを意味する。
hash.apple = 100と同じ事である。
hash['lemon'] = 200も同じだ。

見た目はhash配列にappleをキーとして値に100を設定しているように見えるが、
全く違うのだ。

それでは以下の部分はどうだろう。
for(key in hash){
  var ret = hash[key];
} in演算子は対象のオブジェクトが指定された名前のプロパティを
保持しているかどうかを確認する。(true/falseが返る。)
forと組み合わせる事によって、指定オブジェクトの各プロパティ名を
取得していくことができる。

だから
hash[key]は、hashオブジェクトのkeyプロパティに設定された値を
取得することを意味する。
上記の例でいうとプロパティにapple、lemonを追加したから、
hash['apple']、hash['lemon']の値を取得することになる。
hash.apple、hash.lemonでもかまわない。

補足だがプロパティが数値の場合は、ドットを利用したアクセスはできない。
hash['1000'] -> OK
hash.1000    -> NG エラーになる。

つまり、JavaScriptにおけるハッシュテーブルに似た仕組みの裏側は、
オブジェクトにプロパティを設定するという行為である。

考察
コードを書いて少しでも動いてしまうと、
同じようなケースに遭遇したときに、
動作原理について知らないまま
経験に基づいてコードを書いてしまうことが少なくない。
理論ではなく経験則に基づいてということだ。

これは非常に危うい。
プログラムの複雑さが増し問題にぶちあたった時に、
原理を知らないからそれに基づいて問題解決に取り組む事ができないからだ。
当然経験も無いので何から手をつけたらいいかわからなくなる。

しかし原理を知らないまま書く事が悪いといっている訳ではない。
どのような動作をするかを知るためには、
体で理解すること、反復練習をすること
つまり何度も同じようなコードを自分の手で書くことで、
体にしみ込ませる事が必要だと思うからだ。

重要なのは、体がわかるようになり余裕が出てきた時に
なぜそのような動作になるかを知ることだと思う。
経験と原理両面から知る事で深い理解につながる。

算数・数学などの公式なども一緒だと思う。
公式の意味するところは最初はわからないが、
問題を数多くこなす事につれ体と頭が理解するようになる。

人間何かを学ぶためには、理論と経験の両輪で考えなければならない。

0 件のコメント:

コメントを投稿