JavaScriptの基本技メモ

JavaScriptをいまひとつ使いこなせていないので、Pragmatic Guide to JavaScriptの1〜3章を参考に、JavaScriptの基本的なテクニックを再学習しました。

動作環境

サンプルプログラムを手元で動かす環境として、node.js (0.8.14) を使いました。今回の範囲ではDOMを使わないので、ブラウザ上で実行するよりもこちらの方がお手軽に試せると思います。

ブラケットを用いたメソッドの動的な選択

オブジェクトのプロパティを参照する手段として、object.memberとobject[member]の2種類がありますが、前者は静的なメンバ名しか指定できないのに対して、後者は実行時の式の評価結果をメンバ名として指定することができるという違いがあります。
メソッドに対しても同様の規則が使えるので、式の評価結果によって異なるメソッドを呼び出すことができます。

if文を使った場合:

myObj = Object();

myObj.hello = function() {
  console.log('Hello.');
}
myObj.bye = function() {
  console.log('Bye.');
}

var sayHello = true;
if (sayHello) {
  myObj.hello();
} else {
  myObj.bye();
}
// => Hello.

ブラケットの記法を使って、上記のif文を以下のように置き換えることができます。

myObj[sayHello ? 'hello' : 'bye']();

無名関数を使ったスコープ作成

キーワードvarを用いたローカル変数のスコープは、変数を定義した関数の内側となるので、以下のように無名関数を使ってスコープを限定することができます。

(function() {
  var localVariable = 'some value';
  ...
})();

試しに、無名関数の内側で定義した変数を、外側から参照してみます。

(function() {
  var message = 'Hello, world';
  console.log('Inside the function: ' + message); 
})();
console.log('Outside the function: ' + message);

実行結果:

$ node local.js 
Inside the function: Hello, world

/tmp/local.js:6
console.log('Outside the function: ' + message);
                                       ^
ReferenceError: message is not defined

応用ワザとして、無名関数からローカル変数をプロパティとするオブジェクトを返すことで、関数の外側からのアクセスが可能になります。

var obj = (function() {
  var message = 'Hello, world';
  return { message: message };
})();

console.log('Outside the function: ' + obj.message);
// => Outside the function: Hello, world

argumentsを用いた可変長引数

関数の内側ではargumentsという名前の配列が自動的に定義され、ここにすべての実引数が入ります。

サンプル:

function func() {
  for (var i = 0; i < arguments.length; i++) {
    console.log('arguments[' + i + ']: ' + arguments[i]);
  }
}

func(10, 20, 'foo');

実行結果:

arguments[0]: 10
arguments[1]: 20
arguments[2]: foo

オブジェクトを用いた擬似的なキーワード引数とデフォルト値

Rubyなどでもよく用いられる、ハッシュを使った擬似的なキーワード引数と同様のテクニックです。ここでは、指定されなかったキーワードについてデフォルト値を設定しています。

function repeat(options) {
  options = options || {}; // optionsがfalseと等価な場合は空のオブジェクトを代入
  for (var opt in repeat.defaultOptions) {
    // 指定されないキーワードについてデフォルト値に置き換え
    if (!(opt in options)) {
      options[opt] = repeat.defaultOptions[opt];
    }
  }

  for(var i = 0; i < options.times; i++) {
    console.log(options.message);
  }
}
// デフォルト値のセット
repeat.defaultOptions = {times: 2, message: 'Hello, world'};

repeat(); //=> 'Hello, world' が2回表示される
repeat({times: 3}); //=> 'Hello, world' が3回表示される
repeat({message: 'Good evening.'}); //=> 'Good evening.' が2回表示される
repeat({times: 1, message: 'Good bye.'}); //=> 'Good bye.' が1回表示される

メモ: falseと評価される値は以下の通り。

  • undefined
  • null
  • 0
  • NaN
  • 空文字列 ('')