スタッフブログ

  • 最新配信
  • RSS

prototype.js 1.6のクラス機構

 : 技術全般 2009/1/21 11:02

Blogger's Avatar

satoです。

JavaScriptのライブラリでお馴染みのものにPrototype(prototype.js)があります。
このライブラリは、早い段階からJavaScriptでクラス機構を実現するための仕組みが用意されていたのですが、あまり使い勝手がいいと言えるものではありませんでした。

一昨年くらいに1.6がリリースされて、クラス作成周りが一新されたのですが、あまり情報がない(というか、あるのですが古い情報が優先して検索される)ので、ここでも書いておこうと思います。

■クラス作成
・1.5以前

var Animal = Class.create();
Animal.prototype = {
initialize: function() {
this.name = 'Animal';
},
getName: function() {
return this.name;
}
};

alert(new Animal().getName()); // 'Animal'


・1.6

var Animal = Class.create({
initialize: function() {
this.name = 'Animal';
},
getName: function() {
return this.name;
}
});

alert(new Animal().getName()); // 'Animal'


Class.createの中に直接書けるようになりました。ちなみに1.5以前の書き方でも通るようになっていますが、この後の継承などで問題が出ると思うので、1.6の書き方を使うようにしましょう。

■継承
・1.5以前

var Animal = Class.create();
Animal.prototype = {

initialize: function() {
this.name = 'Animal';
},
getName: function() {
return this.name;
}
};
var Cat = Class.create();
Object.extend(Cat.prototype, Animal.prototype);
Object.extend(Cat.prototype, {
initialize: function() {
this.name = 'Cat';
}
});

alert(new Animal().getName()); // 'Animal'
alert(new Cat().getName()); // 'Cat'


・1.6

var Animal = Class.create({
initialize: function() {
this.name = 'Animal';
},
getName: function() {
return this.name;
}
});
var Cat = Class.create(Animal, {
initialize: function() {
this.name = 'Cat';
}
});

alert(new Animal().getName()); // 'Animal'
alert(new Cat().getName()); // 'Cat'



Object.extendを使わなくなったのが大きな違いです。
そもそもObject.extendの実装を見ると、

Object.extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
}

のように、プロパティをコピーしているだけで、継承と呼ぶには厳しい実装でした。どちらかといえばmixinに近い実装だと思います。

1.6の実装になって何が嬉しいかと言うと、
・書き方がわかりやすい
Object.extendを複数回呼ぶ必要もありませんし、明示的にprototypeを指定する必要もなくなりました。

・親クラスのメンバを呼べるようになった
恐らくこれが一番大きいです。
1.5では、

var Cat = Class.create();
Object.extend(Cat.prototype, Animal.prototype);
Object.extend(Cat.prototype, {
initialize: function() {
this.name = 'Cat';
},
getName: function() {
return (Animal.prototype.getName.bind(this))() + 'だよ';
}
});

alert(new Animal().getName()); // 'Animal'
alert(new Cat().getName()); // 'Catだよ'


のような強引な手法を採るしかありませんでしたが、1.6では、


var Cat = Class.create(Animal, {
initialize: function() {
this.name = 'Cat';
},
getName: function($super) {
return $super() + 'だよ';
}
});

alert(new Animal().getName()); // 'Animal'
alert(new Cat().getName()); // 'Catだよ'


のように、第一引数を$superという名前にすると、そこに親クラスのメソッドが入るようになりました。
ちなみにこの場合、getNameに引数を渡して受け取る場合、第二引数以降に割り当てられます。

getName('hoge') → getName: function($super, hoge) {

みたいな感じです。

■まとめ
そもそもクラスとか定義するのはJavaScriptっぽくない感じはするのですが、単純に慣れているというのと、可読性が向上するという意味で積極的に使うようにしています。
最近はjQuery派とフルスクラッチ派が強い印象がありますが、prototype.jsは基本機能が整っていて、今でも十分実用的に使えるライブラリだと思います。

トラックバック

スタッフブログ最新
カテゴリ一覧

〒104-0061 東京都中央区銀座1丁目3番3号 G1ビル7階
お問い合わせ TEL 03-3524-8860

Copyright(c) 2012 RYUS.All Rights Reserved.