nyuhuhuu cc |
パーフェクトJavaScript (PERFECT SERIES 4)
1. 変数の存在チェック(ReferenceError例外の発生を修正する)
宣言していない変数から値を取り出そうとするとReferenceError例外が起きる。この例外を回避する方法を挙げていく。// 遅延評価を利用する var a = a || 7; // aが既に値を持っていれば変数aの値を使う(イディオム) // aが厳密にundefiendかどうか調べる その1 var a; // 既に定義されている場合は値はそのまま変わらない var b = a !== undefined ? a : 7; // aが既に値を持っていれば変数aの値を使う // aが厳密にundefiendかどうか調べる その2 if (typeof a !== 'undefined') { var b = a; } else { var b = 7; } // aが宣言済みか(存在するか)を調べる if ('a' in this) { var b = a; } else { var b = 7; }
2. new式の挙動
コンストラクタは以下のように書く。function MyClass(x, y) { this.x = x; this.y = y; }
これをnewしてオブジェクト(インスタンス)を生成する。このときのnew式の動作は以下のようになる。
- 空のオブジェクト{}を生成する
- new式で指定した関数(コンストラクタ)を呼び出す
- this参照がオブジェクトのプロパティとなる
3. フィールドとメソッドを持つクラス定義
Javascriptにはクラスはないけれど、コンストラクタ(関数)によりフィールドとメソッドを持つクラスのようなものを定義できる。// クラス定義に相当 function MyClass(x, y) { // フィールドに相当 this.x = x; this.y = y; // メソッドに相当 this.show = function() { print(this.x, this.y); } } js> var obj = new MyClass(3, 2); js> obj.show(); // => 3 2ただしこのコードには以下の問題がある。
- このコンストラクタをnewして生成されるインスタンスにはすべて同じshowメソッドが定義されるため、メモリ効率と実行効率がよくない
- プロパティ値のアクセス制御(privateやpublic)ができない
4. プロトタイプ継承
上のコードには共通するshowメソッドをすべてのインスタンスのプロパティにコピーしてしまうため効率が悪かった。これをプロトタイプ継承を使って書き換えると以下のようになる。function MyClass(x, y) { this.x = x; this.y = y; } MyClass.prototype.show = function() { print(this.x, this.y); } js> var obj = new MyClass(3, 2); js> obj.show(); // => 3 2このとき生成したインスタンスオブジェクトobjはプロパティにshowを持たないが、prototypeオブジェクトのプロパティshowを継承している。
5. プロトタイプチェーン
パーフェクトJavascriptの138ページにいろいろ説明があるけど、要約するとメソッド呼び出しの優先順位は- オブジェクト自身のプロパティ
- コンストラクタのprototypeオブジェクトのプロパティ
- さらにprototypeをたどって得たプロパティ