2007-06-22

javascriptを理解するためのたった2つの大切なこと:改

9割ぐらいはハッシュ

何がハッシュなのか

javascript存在するほとんどオブジェクトの実体はハッシュだよ。

var arr = [0,1,2,3];

とかをみると配列(人によってはリスト)に見えると思う。でも実際は違うんだ。

これは

var has = {0:0,1:1,2:2,3:3};

と基本的には等価なんだ。ただちょっと束縛されているメソッド(インターフェイス)が違うだけ。

ためしに

arr[4] = 4;
arr['x'] = 'string';
arr[-1]  = -1;

としてみよう。

Firebugで確認してみると[0, 1, 2, undefined, 4]というような値がかえってくるよ。

でもarr[-1]やarr['x']の値は保存されてないのかな?そんなことはないちゃんとアクセスできるんだ。

それどころかarr.xで'string'がかえってくるんだ。

別の例を見てみよう。

var fx = function(){};
fx[0] = 'somestring';

こうするとfx[0]に'somestring'が束縛される。

つまりfunctionも一つのハッシュだったんだ。

これでほとんどのものがハッシュだということが解ってくれたかな?

ハッシュじゃないのは文字列とか数字とかそいういシンプルなものだけなんだ。

ハッシュへのアクセス

ハッシュへはhash[name]でアクセスすることが出来る。

それ以外にもname演算子や空白を含まなくて頭が数字でない場合はhash.nameでアクセスできるんだ。

これでhash[name]が関数だったらhash.name(args)とできるよ。まるでメソッドみたいだね。

関数のあれこれ

無名関数

関数には名前を付けなくても使用可能だよ。

function(x){return x+x}(2); -> 4
宣言文

関数宣言の書き方って次見たいの覚えてる人が多いんじゃないかな?

function funcname(args){ do something};

でもこれはsystax sugerだってことを知ってほしい。

上でも使ってるんだけど。

var funcname = function(args){ do something};

等価になる。もちろんどちらの書き方でもかまわないよ。

ただ、(無名)関数を宣言してそれをfuncnameに束縛しているっていうことを理解しておくと便利だよ。

スコープ closure

javascriptレキシカルスコープを採用してるんだ。

レキシカルスコープなんていうと難しく感じるかもしれないけど、結構単純なんだ。

var x = 'global';
var fx1 = function(){return x};
var fx2 = function(){var x = 'local';return x}

これの実行結果は以下になるよ。

fx1() -> 'global'
fx2() -> 'local'
fx1() -> 'global'

fx2の変数xはほかの場所に影響しないんだ。これは関数の中と外ではスコープが違うからなんだ。

でも以下のような場合に注意してほしいな。

var x = 'global';
var fx1 = function(){return x};
var fx2 = function(){x = 'local';return x}
fx1() -> 'global'
fx2() -> 'local'
fx1() -> 'local'

fx2は自分のスコープ変数xがないからその外側スコープに探しに出かけたんだ。

つまり宣言文varはそのスコープに新しい名前を登場させる機能なんだよ。

別の場合を見てみようね。

var x = 'global';
var fx1 = function(){
  var x = 'local';
  return function(){return x}
};
var fx2 = fx1();
x -> 'global'
fx2() -> 'local'

この例だとfx2()の値がlocalになってるね。

なぜなら外側スコープっていうのは関数を評価した場所じゃなくて、関数を定義した場所の外側なんだ。

関数は返り値として関数ハッシュを指定できるよ。

一つ上の例では実際に関数を返り値にしているね。

戻り値関数を指定するとこんなことが出来るよ。

var fx1 = function(){
  var x = 0;
  return function(){
    x = x+1;
    return x;
  }
};
var fx2 = fx1();
var fx3 = fx1();
fx2() -> 1
fx2() -> 2
fx2() -> 3
fx3() -> 1
fx3() -> 2

fx2とfx3の値が違うのはそれぞれ別の関数が作られるからだよ。

こんな風に関数が状態を持つことも出来るんだ。クロージャーとよんだりするよ。

関数ハッシュを使って複数の関数を返すとこんなことも出来るよ。

var fx = function(){
  var x = 0;
  return {
    'up':function(){
      x = x+1;
      return x;
    },
    'down':function(){
      x = x-1;
      return x;
    }
  }
};
var obj = fx();
obj.up(); -> 1
obj.up(); -> 2
obj.down(); -> 1
obj.down(); -> 0

最後に一度ハッシュについてもうちょっとだけ。thisのはなし。

thisという機能があるよう。ちょっとだけつかってみるね。

var x = 0;
var add = function(n){this.x = this.x + n; return this.x};
var mul = function(n){this.x = this.x * n; return this.x};
var obj = {'x':0,'do':add};
add(1);   -> 1
add(1);   -> 2
mul(2);   -> 4
obj.do(); -> 1
obj.do(); -> 2
obj.do = mul;
obj.do(); -> 4

thisは評価された場所によって値がかわるよ。

objの中にいるときはobj.xを扱うし、グローバルにいるときはグローバルのxを扱うんだ。

http://anond.hatelabo.jp/20070620200618を改訂してみたよ。

このぶんしょうがjavascriptを覚える上の一助になるとうれしいんだ。

あとここでつかってるハッシュ伝統的な意味連想配列のことね。

突っ込みも大歓迎だよ。

トラックバック - http://anond.hatelabo.jp/20070622101313

記事への反応(ブックマークコメント)