Effective JavaScriptを読んだよ

Effective JavaやらEffective C++やらありますが、Effective JavaSctiptというのもありまして。書籍になっているわけではないですが。

Effective Java 第2版 (The Java Series)

Effective Java 第2版 (The Java Series)

Effective C++ 原著第3版 (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

Effective C++ 原著第3版 (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

で、今までちゃんと読んだことがなかったので読み進めることにしました。
書いてあるのは知らなかったところだけ、になる予定。

引数チェック

引数がオブジェクトを要求する場合に、特定クラスのオブジェクトかどうか調べる方法。

function useDate(oDate) {
  if (!(oDate instanceof Date)) {
    return;
  }
}

この場合、instanceofで引数を調べているので、Dateか、Dateの派生オブジェクトはif文の中を通らない。
派生オブジェクトすらも渡されたくない場合はコンストラクタを調べると良いみたい。

if (!oDate.constructor || oDate.constructor !== Date) {
  return;
}

引数のオブジェクトがconstructorを持っていない、もしくはコンストラクタがDateのものと一致しない場合はreturnします。

残余引数

arguments.lengthって知らなかった!

function a() {
  console.log(arguments.length);
}
a(1);        // 1
a(1, 2);     // 2
a(1, 2, 3);  // 3

これを利用してprintfみたいな、後ろにいくつ引数が来るかわからない関数を作るには。

function foo(a, b /* , ... */) {

  var len = arguments.length,
      args = Array.prototype.slice.call(
        arguments,
        len - arguments.callee.length - 1,
        len);

  console.log(args);
}
foo(1,2,3,4,5);  // [3, 4, 5]

という感じ。Array.prototype.slice.callはお決まりの、argumentsを本当の配列に直すやつ。
callee使ってるのがなー……

関数アダプタ

自分もよくC言語で言うstatic変数代わりによく使う方法。

function aaa() {

  var count = aaa.count || 0;

  console.log(count++);
  aaa.count = count;
}
aaa();  // 0
aaa();  // 1
aaa();  // 2
function aaa() {

  var count = aaa.count || 0;

  console.log(count++);
  aaa.count = count;
}
aaa.count = 500;
aaa();  // 500
aaa();  // 501
aaa();  // 502

クロージャ使えって?そうですねえ……

関数の変形 / 復習

遅延評価!

function plus(x, y) {
  return function () {
    return x + y;
  };
}
var f = plus(3, 4);
f();  // 7

まだ遅延評価が必要になる場面に会ったことが無い……

関数の合成

関数型っぽい考え方が出てきた……
パラダイムシフト出来てないのでさっぱりです。

クラスメンバ

必要になったことないけど、必要になりそうなので。こうやって書くのか。
てか、関数アダプタのところと大して変わらないような。

function Person(nAge) {
  this.m_nAge = nAge;
  if (Person.m_nPopulation !== undefined) {
    ++Person.m_nPopulation;
  }
}

Person.m_nPopulation = 0;

var Don = new Person(22),
    Exeal = new Person(21);

Person.m_nPopulation;  // 2
Don.m_nPopulation;     // undefined?

継承

継承も書いたこと無いかな……
PDFには2つ書いてあるんだけど、2つ目だけを以下に。

function Programmer(nAge, strProject) {
  Person.call(this, nAge);
  this.constructor = Programmer;
  // Programmerコンストラクタの処理
}

node.jsかなんかでも最近見たような。constructorは代入してなかったと思うけど。


続いてメソッドの継承を。書き方は知ってたけど意味を良く知らなかった。

Programmer.prototype = new Person();
  1. Personインスタンスを作成し、Programmerコンストラクタのプロトタイプにセットする
  2. PersonインスタンスのプロトタイプはPersonのプロトタイプである
  3. Programmer.prototypeのプロトタイプはPersonのプロトタイプである
  4. ProgrammerのプロトタイプのプロトタイプはPersonのプロトタイプである

なんのこっちゃ。あとでじっくり読んでみよう。


後半は流し読みした。privateとかpublicとか、JavaScriptパターンだったかな、を読んだから。
と言ってもモジュールパターンしか試したこと無いんだけど……
モジュールパターンで委譲すりゃいいのかなーとおぼろげながら思ってるけど、そのうちそれじゃだめなところとか出てくるんだろう。


というわけでEffective JavaScriptをまだ読んでいない方は一度ご覧あれ。
でも大昔に読んだ覚えがあったけど、当時意味わかんなくて数ページも読めなかったと思う……
なのでJavaScript: The Good PartsとかハイパフォーマンスJavaScriptとかJavaScriptパターンとかで予習すると良いのかもしれません。
なんでJavaScript第5版(6版でてるんだっけ?)とか初めてのJavaScriptとかパーフェクトJavaScriptが出てこないかって言うと、まだ読み終わってないからだよ!

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

ハイパフォーマンスJavaScript

ハイパフォーマンスJavaScript

JavaScriptパターン ―優れたアプリケーションのための作法

JavaScriptパターン ―優れたアプリケーションのための作法

JavaScript 第5版

JavaScript 第5版

初めてのJavaScript 第2版

初めてのJavaScript 第2版

パーフェクトJavaScript (PERFECT SERIES 4)

パーフェクトJavaScript (PERFECT SERIES 4)

……てかなんで初めての〜を読まなかったんだろう。ページ数少ない方が読みやすいけども。