サイ本要約 9章 クラスとコンストラクタとプロトタイプ
- 作者: David Flanagan,村上列
- 出版社/メーカー: オライリー・ジャパン
- 発売日: 2007/08/14
- メディア: 大型本
- 購入: 50人 クリック: 911回
- この商品を含むブログ (263件) を見る
9.1 コンストラクタ
記述例
function Rectangle(w, h){ this.width = w; this.height = h; // return文は記述しない } var rect1 = new Rectangle(2, 4); var rect2 = new Rectangle(8.5, 11);
オブジェクトの生成方法
- オブジェクトリテラルで{}と記述する
- ex.) var point = {x:0, y:0};
- コンストラクタ関数を使う
-
- ex.) var today = new Date();
コンストラクタ関数とは
thisとは
- 実行中のコード*3が「自分自身」を表すオブジェクトにアクセスするためのキーワード
- thisキーワードから参照されるオブジェクトは実行時にならないと決まらない
- トップレベルのコード・関数内でthisを利用すると、『グローバルオブジェクト』を指す
参考:
"JavaScriptのthisキーワードをちゃんと理解する" http://builder.japan.zdnet.com/script/sp_javascript-kickstart-2007/20371112/1/
"JavaScript の this について" http://d.hatena.ne.jp/amachang/20070917/1190015123
new演算子の挙動
- 空のオブジェクトを生成する
- そのオブジェクトに対してプロトタイプ(後述)を設定する
- そのオブジェクトのメソッドとしてコンストラクタ関数を呼び出す
9.2 プロトタイプと継承
プロトタイプと継承とは
- すべてのオブジェクトにはプロトタイプオブジェクトというオブジェクトへの参照が含まれている
- オブジェクトはプロトタイプからプロパティを継承する*4
ややこしいこと
- コンストラクタ関数のprototypeプロパティの値がオブジェクトのプロトタイプになる
- すべての関数は定義時に自動的にprototypeプロパティが生成され、値が設定される
- prototypeプロパティの初期値はconstructorプロパティしかプロパティがないオブジェクト
- このconstructorプロパティはコンストラクタ関数自身を参照する*5
つまり、すべてのオブジェクトで使うものは、prototypeオブジェクトのプロパティとして追加することで
プロパティの継承によってすべてのオブジェクトで利用可能になる。
9.3 JavaScriptの「クラス」
オブジェクトというデータ型をサポートするもののクラスという正式な概念はない。
しかし、前述のプロトタイプベースの継承を行うことが出来る。
用語の説明
クラスプロパティの記述例
Rectangle.UNIT = new Rectangle(1, 1);
コンストラクタ関数(JavaScriptでは関数はオブジェクト)にプロパティUNITを追加することでクラスプロパティを実装している。
- クラスメソッド
- クラスに関連付けられたメソッド(Date.parse()など)
プライベートメンバ
JavaScriptではクロージャを使って実現する。
function ImmutableRectangle(w, h){ // width と height の値がクロージャのスコープチェーン中に閉じ込められる this.getWidth = function(){ return w; } this.getHeight = function(){ return h; } }
9.4 オブジェクト共通メソッド
JavaScriptで新しいクラスを定義する場合に、定義しておくべき関数
- toString()メソッド
// 例 Circle.prototype.toString = function(){return "[Circle of radius " + this.r + "]"}
- valueOf()メソッド
- toString()と同じように使われるが、オブジェクトを文字列以外の基本型に変換する必要があるときに自動的に呼び出される
- 比較用のメソッド
- equals()メソッド
- 「参照による比較」ではなく「値による比較」を行いたいときに使う
- compareTo()メソッド
- ソートする必要があるなら定義しておく
- equals()メソッド
9.5 スーパークラスとサブクラス
JavaScriptではプロトタイプチェーンを使って実現する。
記述例
// スーパークラス function Rectangle(w, h){ this.width = w; this.height = h; } Rectangle.prototype.are = function(){return this.width * this.height;} // サブクラス function PositionedRectangle(x, y, w, h){ // コンストラクタチェーン // スーパークラスのコンストラクタを呼び、プロパティを初期化 Rectangle.call(this, w, h); // 長方形の左上の座標を保存 this.x = x; this.y = y; } // Rectangle のサブクラスにするにはプロトタイプオブジェクトを明示的に生成する // デフォルトのプロトタイプオブジェクトではObjectの直接のサブクラスになるため PositionedRectangle.prototype = new Rectangle(); // スーパークラスのwidth, heightプロパティは継承したくないので削除 delete PositionedRectangle.prototype.width; delete PositionedRectangle.prototype.heith; // プロトタイプオブジェクトはRectangle()コンストラクタと一緒に生成されるので // Rectangle()を参照するconstructorプロパティを持つ。 // PositionedRectangle()コンストラクタを参照するように書き換える PositionedRectangle.prototype.constructor = PositionedRectangle; // 準備完了 // インスタンスメソッドを追加してみる PositionedRectangle.prototype.contains = function(x, y){ return (x > this.x < this.x + this.width && y > this.y && y < this.y + this.height); } var r = new PositionedRectangle(2, 2, 2, 2); print(r.contains(3, 3)); // インスタンスメソッド print(r.area()); // 継承したインスタンスメソッド
コンストラクタチェーン
サブクラスのコンストラクタ関数内で明示的にスーパークラスのコンストラクタ関数を呼び出す処理のこと。
// 1階層のサブクラスしか持たない場合はサブクラスのプロトタイプオブジェクトに // superclassという名前のプロパティを追加すれば簡潔に書ける PositionedRectangle.prototype.superclass = Rectangle; function PositionedRectangle(x, y, w, h){ this.superclass(w, h); this.x = x; this.y = y; }
オーバーライド
サブクラスでスーパークラスと同じ名前のメソッドを定義すると、サブクラスはそのメソッドをオーバーライドする。