Javascript初心者に初心者++程度の自分が言語仕様を説明したときのメモ(第五回)
Javascript初心者に初心者++程度の自分が言語仕様を説明したときのメモ(第四回)の続き
今回はnewの動作について。ほぼ、以下のリンクの和訳。。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new
- 新しいオブジェクトを作り、コンストラクタ関数のprototypeを引き継ぐ。
- コンストラクタ関数を実行する。その際、thisには1で作られた新しいオブジェクトを設定する。
- 戻り値として、1で作られた新しいオブジェクトを返す。ただし、コンストラクタ関数内で、プリミティブ以外の値が返されているときは、その値が返され、1で作られた新しいオブジェクトは返されない。
function foo() { // コンストラクタ関数 this.a = 1; // このthisはnewした場合は2.のとおり、あたらいオブジェクトを指す // 何もreturnしていないが、this(新しく作られたオブジェクト)が返される } foo.prototype.getA = function() { // この内容が引き継がれる return this.a; } var obj = new foo(); // () がなくても同様に動作する。
こんなとこなのだけれども、ここで、さらっと書いた1の「コンストラクタ関数のprototypeを引き継ぐ」についてもうちょっと深堀りをしていこうと思う。
この引継の動作を理解するにあたっては、Javascriptの以下の特性を抑えていく必要がある
参考:http://zeekat.nl/articles/constructors-considered-mildly-confusing.html#sec-1
- すべてのオブジェクトには内部的にprototypeというプロパティを持っている。以下、この内部的なprototypeを[prototype]と表記。
- [prototype]はobj.prototypeとイコールではない。
- [prototype]を直接読み込む方法はない
- objの任意のプロパティが参照されたとき、そのプロパティが存在しない場合に、[prototype]が参照される
- デベロッパーコンソールとかで見られる__proto__とかが[prototype]を指しているので、アクセスできるかもしれないが、今のところこの__proto__へのアクセスは推奨されていない。このへんは「ECMAScript」とかそのあたりをググりながら別途調べてください。
- [prototype]はオブジェクト生成時以外には書き込みできない
※実際は、コンストラクタ関数以外にもObject.create()などのオブジェクト生成方法があるけど、ややこしくなるのでここでは触れない
つまり、前回のプロトタイプチェーンの話で触れた「prototypeをたどる」という動作は、[prototype]の内部で起っているということになる。
前から、なんで以下のように、newして作ったオブジェクトのprototypeにアクセスできないのか不思議に思っていたのだけども、これでなっとくできた。
hoge = new Hoge(); hoge.prototype.a = 1 // TypeError: Cannot set property 'a' of undefined
そして、なんでアクセスできないような仕様になっているのかというと、継承関係がカオスになるからなんだろうなぁ、となんとなく思っておくくらいで、今回は済ませておくことにしました。
- 出版社/メーカー: 任天堂
- 発売日: 2014/05/29
- メディア: Video Game
- この商品を含むブログ (45件) を見る