リア充爆発日記

You don't even know what ria-ju really is.

Javascript初心者に初心者++程度の自分が言語仕様を説明したときのメモ(第五回)

Javascript初心者に初心者++程度の自分が言語仕様を説明したときのメモ(第四回)の続き

今回はnewの動作について。ほぼ、以下のリンクの和訳。。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new

  1. 新しいオブジェクトを作り、コンストラクタ関数のprototypeを引き継ぐ。
  2. コンストラクタ関数を実行する。その際、thisには1で作られた新しいオブジェクトを設定する。
  3. 戻り値として、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

そして、なんでアクセスできないような仕様になっているのかというと、継承関係がカオスになるからなんだろうなぁ、となんとなく思っておくくらいで、今回は済ませておくことにしました。

マリオカート8

マリオカート8