プログラマのkinuです。普段よく使いますがあまり理解せずに使ってたjavascriptのオブジェクトについて調べました。
javascript はオブジェクト指向プログラムをサポートした言語です。
PHPなどのクラスを実装し、オブジェクトを生成して動作させるクラスベースのオブジェクト指向ではなく、プロトタイプベースのオブジェクト指向です。プロトタイプというのがどういうものを指してるのかまだ理解できてないですが、とりあえずオブジェクトからオブジェクトを生成して動作させるということはなんとなくわかりました。
生成のしくみ
javascript のオブジェクト生成の単純な例です。
[code]
var A = function (x) {
this.x = x;
};
A.prototype.x = 0;
var a = new A(1);
[/code]
[コード1]
http://d.hatena.ne.jp/maeharin/20130215/javascript_prototype_chain
の記事を参考にインスペクタでのぞきながら自分なりに図にまとめました。
[図1]
四角はオブジェクト、矢印はプロパティです。点線の矢印は構造と直接関係ない補助的なものです。
この図から実際使うオブジェクトのほかにオブジェクトを生成するオブジェクト(コンストラクタ)とベースになるオブジェクト(プロトタイプ)があることがなんとなくわかります。
このままだとわかりづらいので図にまとめると、
[図2]
つまり、コンストラクタをnewするとprototypeプロパティにもったオブジェクトをもとにオブジェクトを生成してくれるということです。あとついでにコンストラクタの処理を生成したオブジェクトで実行してくれます。
__proto__ってなに?
プロパティprotoは内部プロパティprototypeの値でプロトタイプをもってます。
[図1]でいうと、aはA.prototypeを、A.prototypeはObject.prototypeをもっています。
プロパティ(またはメソッド)を使うときにこのprototypeをたどって探索します。これをプロトタイプチェーンといいます。
オブジェクトがオブジェクトを生成する
あらためて[図1]をみると[図2]の形がけっこうみつけられます。
aをみてみるとAでA.prototypeをもとにつくられています。AもFunctionでFunction.prototypeをもとにつくられ、A.prototypeもObjectでObject.prototypeをもとにつくられてます。
この仕組みでオブジェクトが生成されていることがわかりますね。
Object.create()
コンストラクタをnewしてオブジェクトを生成する方法のほかにもオブジェクトを生成する方法もあります。それはObject.create()です。
以下のようにして使います。
[code]
var a = Object.create(Object.prototype);
a.x = 1;
[/code]
[コード2]
これで[コード1]とほぼ同じオブジェクトが生成されます。
「ほぼ」といっているのはコンストラクタから生成したときに自動に設定されるプロパティconstructorがこれでは設定されません。これはinstanceofで使われているプロパティなので使い方によっては注意が必要です。
実は[コード2]はObject.create()がなくても
[code]
var a = {};
a.x = 1;
[/code]
[コード3]
と書いても同じことができます。あれ、Object.create()いらないんじゃ…と思っちゃいそうですが、既存のオブジェクトからオブジェクトをつくるときに役立ちます。
例えば,
[code]
var a = {};
a.x = 1;
var b = Object.create(a);
b.y = 1;
[/code]
[コード4]
のようにすると既存のオブジェクトを簡単に拡張できます。
まとめ
今回はjavascriptのオブジェクトの生成について調べました。
クラスを作らなくてもオブジェクトが作れるのはプロトタイプベースの利点なのかなあなんてふんわり理解できたような気がします。このあたりは実際使うとときがきて実感するんじゃなかろうか。
またクラスベースっぽいふるまいもできるのでそれぞれの特性を生かして使いわけて実装できるという点はすごくいいなと思いました。その分いろいろと知っておく必要はありますが。
あと、今回プロトタイプチェーンという概念がでてきましたがスコープチェーンというのもあるらしいです。まだまだ知らないことも多いですがこれからも暇をみつけて勉強していきたいです。
参考にしたWebページ
- http://d.hatena.ne.jp/maeharin/20130215/javascript_prototype_chain
- http://nanto.asablo.jp/blog/2005/10/24/118564
- http://www.slideshare.net/yuka2py/javascript-23768378
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/create
- http://compute-taso.blogspot.jp/2013/04/objectcreate.html