サイトトップ

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

HTML5テクニカルノート

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

ID: FN1412009 Technique: HTML5 and JavaScript Library: EaselJS 0.8.0

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


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

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

表001■Pointクラスのプロパティとメソッド
コンストラクタ
Point(x, y) 座標(x, y)のインスタンスをつくる。
プロパティ
x x座標値を示す。
y y座標値を示す。
メソッド
clone() プロパティ値が等しい新たなインスタンスをつくって返す。
copy(point) 引数のPointオブジェクトと同じプロパティ値をインスタンスに定める。
setValues(x, y) 引数のxyプロパティ値をインスタンスに定める。
toString() インスタンスを「[Point (x=x座標値 y=y座標値)]」という文字列表現で返す。

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

Pointクラスにコンストラクタとふたつずつのプロパティおよびメソッドを定めると、基本は以下のようなクラス定義になります。クラスが備えるべきメソッドは、JavaScriptではコンストラクタ関数のFunction.prototypeプロパティに定めます。

コンストラクタ(Point())は、Point.setValues()メソッドを呼出します。呼出されたメソッドは、引数があればその値、なければ0を、インスタンスのPoint.xPoint.yプロパティに定めています(「論理演算子を使った条件判定」02「初期化されていない変数に値を与える」参照)。

function Point(x, y) {
  this.setValues(x, y);
}
Point.prototype.setValues = function(x, y) {
  this.x = x || 0;
  this.y = y || 0;
  return this;
};
Point.prototype.copy = function(point) {
  this.x = point.x;
  this.y = point.y;
  return this;
};
Point.prototype.clone = function() {
  return new Point(this.x, this.y);
}
Point.prototype.toString = function() {
  return "[Point (x=" + this.x + " y=" + this.y + ")]";
}


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

CreateJS Suiteのクラスは、実際には名前空間(createjs)に定められています(「CreateJS Suiteのクラスに名前空間が設定される」参照)。Pointクラスはつぎのように、この名前空間にコンストラクタ関数を加えています。なお、名前空間(createjs)はライブラリのクラスすべてが用いますので、すでに初期化されているかを確かめ、されていない場合には新たにObjectインスタンスを与えました。

this.createjs = this.createjs || {};
function Point(x, y) {
  // ...[中略]...
}
// Pointクラスのメソッド定義
createjs.Point = Point;

ただ、コンストラクタ関数(Point())そのものは、名前空間のないまま別にメモリに残ります。名前空間は、クラスなどの重複を避けるための仕組みです。すると、コンストラクタは名前空間だけに置きたいところです。


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

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

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

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

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

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

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

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

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

コード001■EaselJS 0.8.0の実際のPointクラス
  1. this.createjs = this.createjs || {};
  2. (function() {
  3.   "use strict";
  4.   function Point(x, y) {
  5.     this.setValues(x, y);
  6.   }
  7.   var p = Point.prototype;
  8.   p.setValues = function(x, y) {
  9.     this.x = x || 0;
  10.     this.y = y || 0;
  11.     return this;
  12.   };
  13.   p.copy = function(point) {
  14.     this.x = point.x;
  15.     this.y = point.y;
  16.     return this;
  17.   };
  18.   p.clone = function() {
  19.     return new Point(this.x, this.y);
  20.   }
  21.   p.toString = function() {
  22.     return "[Point (x=" + this.x + " y=" + this.y + ")]";
  23.   }
  24.   createjs.Point = Point;
  25. }());

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


作成者: 野中文雄
作成日: 2014年12月23日 「EaselJSのPointクラスの実装を見る」をEaselJS 0.8.0の実装にもとづいて改訂。


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