サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

EaselJSのPointクラスの実装を見る

ID: FN1212004 Technique: HTML5 and JavaScript

EaselJSは、CreateJS Suiteのおおもととなるライブラリです。その中でも備わるプロパティやメソッドが少なくて簡素なPointクラスの実装を見ることは、CreareJSのライブラリを研究するはじめの一歩に適しているでしょう。


01 Pointクラスのプロパティとメソッド

Pointクラスは、コンストラクタの他には、ふたつのプロパティとふたつのメソッドが備わっています(表001)。プロパティはそれぞれ(x, y)座標値を示します。また、Point.clone()メソッドは、同じ(x, y)座標値の新たなオブジェクトを複製します。Point.toString()メソッドは、インスタンスの文字列表現を返します。

表001■Pointクラスのプロパティとメソッド
コンストラクタ
Point(x, y) 座標(x, y)のインスタンスをつくる。
プロパティ
x x座標値を示す。
y y座標値を示す。
メソッド
clone() xyプロパティ値が等しい新たなインスタンスを返す。
toString() インスタンスを「[Point (x=x座標値 y=y座標値)]」という文字列表現で返す。

02 Pointクラスの基本的な中身

Pointクラスにコンストラクタとふたつずつのプロパティおよびメソッドを定めると、基本は以下のようなクラス定義になります。コンストラクタ(Point())からは、別に初期化のメソッド(initialize())を呼出しています。初期化のメソッドは、引数があればその値を、なければデフォルト値をインスタンスのプロパティに定めます。

function Point(x, y) {
  this.initialize(x, y);
}
Point.prototype.x = 0;
Point.prototype.y = 0;
Point.prototype.initialize = function(x, y) {
  this.x = (x == null ? 0 : x);
  this.y = (y == null ? 0 : y);
}
Point.prototype.clone = function() {
  return new Point(this.x, this.y);
}
Point.prototype.toString = function() {
  return "[Point (x=" + this.x + " y=" + this.y + ")]";
}

クラスが備えるべきメソッド(clone()とtoString())は、JavaScriptではコンストラクタ関数のFunction.prototypeプロパティに定めます。また、インスタンスにプロパティが与えられていない場合のプロパティ(xとy)のデフォルト値も、ここに設定しています。


03 名前空間に定めたPointクラス

CreateJS Suiteのクラスは、実際には名前空間(createjs)に定められています(「CreateJS Suiteのクラスに名前空間が設定される」参照)。Pointクラスはつぎのコード001のように、この名前空間にコンストラクタ関数を定め、プロパティやメソッドを備えています。なお、名前空間(createjs)はライブラリのクラスすべてが用いますので、すでに初期化されているかを確かめ、されていない場合には新たにObjectインスタンスを与えました(第1行目。「論理演算子を使った条件判定」02「初期化されていない変数に値を与える」参照)。

コード001■Pointクラスの実質的な中身
  1. this.createjs = this.createjs || {};
  2. createjs.Point = function (x, y) {
  3.   this.initialize(x, y);
  4. }
  5. createjs.Point.prototype.x = 0;
  6. createjs.Point.prototype.y = 0;
  7. createjs.Point.prototype.initialize = function(x, y) {
  8.   this.x = (x == null ? 0 : x);
  9.   this.y = (y == null ? 0 : y);
  10. }
  11. createjs.Point.prototype.clone = function() {
  12.   return new createjs.Point(this.x, this.y);
  13. }
  14. createjs.Point.prototype.toString = function() {
  15.   return "[Point (x=" + this.x + " y=" + this.y + ")]";
  16. }

EaselJSライブラリのPointクラスは、実質的にこのコード001の中身になります。ただ、かなり書き方が煩わしく、とくにコンストラクタ関数のプロトタイプオブジェクト(createjs.Point.prototype)を長々と書連ねるのが気になります。


04 名前のない関数でPointクラスを定める

コンストラクタ関数やそのプロトタイプオブジェクト(Function.prototypeプロパティ)の参照は、つぎのように変数を宣言して予め与えておけば、コードが見やすくなります。また、備えるべきプロパティやメソッドが増えても、コードは楽に書けます。

this.createjs = this.createjs || {};
var Point = function(x, y) {
  // ...[中略]...
}
var p = Point.prototype;
// プロトタイプオブジェクトへのプロパティやメソッドの設定
createjs.Point = Point;

ただし、グローバルにvar宣言した変数は、納めた値や参照は消せても、存在そのものを除くことはできません。多くのクラスを定めるときは、変数が重複するおそれもありますし、要らないものが残ってしまうのはできるかぎり避けたいところです。

var宣言が関数の中であればローカル変数になりますので、外の変数との重複は気にしなくて済み、外から参照されるおそれもありません。そこで、実際のCreateJS Suiteのクラスは、後掲コード002のように名前のない関数の中で定められています。

  1. this.createjs = this.createjs || {};
  2. (function() {
  3.   var Point = function(x, y) {
  1.   }
  1.   createjs.Point = Point;
  2. }());

名前のない関数の中で、コンストラクタはローカル変数(Point)に定めています(第2〜3行目)。そして、この名前のない関数そのものは、変数に入れていません。つまり、メモリには残らないということです。そこで、書き終わりに括弧()を加えて直ちに呼出しています(第20行目)。つまり、つぎのような呼出し方です。

function() { /* ...[中略]... */ }()

ローカル変数(Point)のコンストラクタ関数も、名前のない関数の実行が済めばそのままではメモリから消えます。そこで、関数の最後に名前空間(createjs)に加えているのです(第19行目)。名前空間は関数の外に定められていますから、コンストラクタの参照は保たれます(第1行目)。

コード002■EaselJSライブラリの実際のPointクラス
  1. this.createjs = this.createjs || {};
  2. (function() {
  3.   var Point = function(x, y) {
  4.     this.initialize(x, y);
  5.   }
  6.   var p = Point.prototype;
  7.   p.x = 0;
  8.   p.y = 0;
  9.   p.initialize = function(x, y) {
  10.     this.x = (x == null ? 0 : x);
  11.     this.y = (y == null ? 0 : y);
  12.   }
  13.   p.clone = function() {
  14.     return new Point(this.x, this.y);
  15.   }
  16.   p.toString = function() {
  17.     return "[Point (x="+this.x+" y="+this.y+")]";
  18.   }
  19.   createjs.Point = Point;
  20. }());

コンストラクタの参照が残ってさえいれば、プロトタイプオブジェクトに定めたプロパティやメソッドも使えます。また、名前のない関数内でのvar宣言は、ローカル変数(Pointとp)になりますので、関数の外からは見えなくなります(第3および第6行目)。


作成者: 野中文雄
作成日: 2012年12月24日


Copyright © 2001-2012 Fumio Nonaka.  All rights reserved.