Smashing Node.js に書いてあるEffective Node.jsなこと(第一部を翻訳してみて)

※ 2012-10-18追記
forEachはfilterの間違いでした。修正しておきます。

Smashing Node.js: JavaScript Everywhere (Smashing Magazine Book Series)

Smashing Node.js: JavaScript Everywhere (Smashing Magazine Book Series)

本ブログは東京Node学園祭2012 アドベントカレンダーの1日目の記事です。

さてさて、Smashing Node.jsを読んでます。

読んでいて思ったのですが、非常に良書です。
著者は 前回のNode学園祭で魔法のようなライブコーディングを見せた Guillermo さん。
せっかくなので、Smashing Node.jsで書かれている内容の中で琴線に触れたものはシリーズ化してこのブログで紹介します。

今回はCHAPTER 1: THE SETUPに書かれていることからCHAPTER 4: NODE JAVASCRIPTに書かれている事の中で、EffectiveなNode.jsの活用方法について紹介していきます。

CHAPTER1の翻訳内容:Smashing node chapter 1 メモ
CHAPTER2の翻訳内容:Smashing node chapter2 memo
CHAPTER3の翻訳内容:Smashing node chapter 3 memo
CHAPTER4の翻訳内容:Smashing Node Chapter 4 memo

一応翻訳したところを貼っておきますが、粗く流し翻訳しただけなので、本当に内容を知りたい場合は購入をおすすめします。

■1. キーを一覧するときはObject.keysを使おう。
以下のオブジェクトのkey一覧を得たい場合、(この例では、aとc)

var a = { a: 'b', c: 'd' }

通常の繰り返しは以下のようにする。

for (var i in a) { }

こうすれば i には キーの値が格納される。
でももし Object.prototypeを以下のように書き換えてたとしたら意図しないkeyであるeが取得される。

Object.prototype.e = 'f';

キーのリスト中に e があるのを避けるために、 hasOwnProperty チェックを実行する必要がある。

for (var i in a) { // [a, c, e]
  if (a.hasOwnProperty(i)) {}  //[a, c]
}

でももっと簡単な方法がある。Object.keysを利用すれば簡単だ。

var a = {a: 'b', c: 'd'};
Object.keys(a); // ['a', 'c']

Object.keysを利用しよう。

■2. 配列かどうかをチェックする際はArray.isArrayを使おう。
javascript の typeof 演算子って 配列でも "object" って返すのね。
でも大体の場合、配列は実際に配列かどうかをチェックしたいよね。 objectだと意味ないし。

Array.isArrayは配列だったら true を返し、それ以外なら false を返すぜ!

Array.isArray(new Array) //true
Array.isArray([]) //true
Array.isArray(null) //false
Array.isArray(arguments) //false

■3. 配列の要素に対して処理したい時はforEachが使えるよ。
配列の全部の要素にアクセスしたい時、forEachを使えるよ。
jQueryの $.eachに似ているメソッドね。

[1, 2, 3].forEach(function (v) {
  console.log(v);
});

配列の中から要素をフィルタするときはこんな風にすればいい。
jQueryの$.grepに似ているメソッドね。

[1, 2, 3].filter(function(v) {
  return v < 3;
});  // will return [1, 2]

各要素の値を変えたい時はmapを使えるよ。
jQueryの $.map と似ているやつね。

[5 ,10, 15].map(function(v) {
  return v * 2;
}); // will return [10, 20, 30]

あとreduceやreduceRight、lastIndexOfなんかも使えるよ。

■4. 文字列のトリミングする時はのメソッド、String#trimを使おう。
文字列の前後の空白を除去する、つまり trim するときは、コレが使える。

'   hello    '.trim(); // 'hello'


■5. 関数には名前を付けよう。
v8では、非標準プロパティとして関数の name プロパティがサポートされてる。

var a = function woot () {};
a.name == 'woot'; // true

このプロパティは 内部的に v8 のスタックトレースで使われている。エラーが投げられた時に、 v8 はスタックトレースを表示するんだ。これが関数呼び出しパスを表示してくれるからどこでエラーが発生したかを特定しやすいんだ。
だけど、無名関数だと名前が表示されない。

> var woot = function() {throw new Error(); }
> woot();
Error
at [object Context]:1:32

この場合、v8 は関数の参照名を特定できないんだ、でも名前をつければ特定できる、だから v8 では以下のように書けばスタックトレースに名前が出てくる。

> var woot = function buggy () { throw new Error(); };
> woot()
Error
at buggy ([object Context]:1:34)

デバッグの時に便利になる。だから関数に名前をつけるべきだ。

■6. __proto__ を利用した継承
継承の時に __proto__ を使うと継承チェインが定義しやすい。

function Animal() {  }
function Ferret() {   }
Ferret.prototype.__proto__ = Animal.prototype;

※Nodeのhelperメソッドである util.inherits を使うのもいいのかもしれないと思ったけど、本書に言及はなかった。

■7. 例外処理
Nodeアプリケーションは巨大なプロセスに依存したたくさんの状態を持っている。

HTTPリクエストのコールバック中にエラーが発生したらどうなるだろう。
以下のコードを見て欲しい。

var http = require('http');

http.createServer(function () {
  throw new Error('This will be uncaught');
}).listen(3000);

このエラーはキャッチされない。webサーバーにアクセスした直後にプロセスがクラッシュするだろう。

キャッチされない例外があるとプロセスの状態は不確かになるからNodeはこんなふうに振る舞うんだ。

ハンドリングされないエラーが発生したら、デバッグも出来ず、予期しない方法で落ちる。この振る舞いを変えたければ、 uncaughtExceptionハンドラを追加することだ。キャッチされない例外が発生した場合、プロセスをどうするのかはプログラマに決定権がある。

process.on('uncaughtException', function (err) {
  console.error(err);
  process.exit(1); //手動で落とす。
});

errorイベントの発行方法はAPIで共通化されている。例えば、以下の例のように、TCPサーバーを構築して、telnet から接続する場合を検討しよう。

var net = require('net');
net.createServer(function (connection) {
  connection.on('error', function (err) {
    // err is an Error object
  });
}).listen(400);

httpやnet等のnative モジュールでは大体こんな感じにerror イベントを発行するように設定している。もしこれらのイベントがハンドリングできない場合は、キャッチされない例外が投げられる。

非同期なNode APIではコールバックの最初の引数としてエラーを渡すこともある。以下の様なコードになる。

var fs = require('fs');

fs.readFile('/etc/passwd', function (err, data) {
  if (err) return console.error(err);
  console.log(data);
});

errorイベントを発行するにせよ、第一引数に渡すにせよ、安全なプログラムを書くのであれば、エラー処理は必須だ。参考にしてほしい。

■まとめ
というわけで、ひとまず7点紹介しました。他にもいっぱいあるので、良ければ翻訳先も参考にしてもらえると幸いです。でも全てを翻訳したわけではないので、本格的に読みたければ購入をオススメします。非常に良書なので、持っていて損はない一冊です。

日本にはまだNode.jsに関する書物が少ないです。なのでこういう洋書で知識補完をする必要があるのですが、今度mesoさん達が書いた本が出ます。

サーバサイドJavaScript Node.js入門

サーバサイドJavaScript Node.js入門

初のまとまった書籍になると思うので、これも一緒に購入しておいて損はないと思います。

それでは、東京Node学園祭2012 アドベントカレンダー始まるよー!