2019/9/21 javascript オブジェクトについての整理

Inheriting properties

JavaScript objects have a link to a prototype object. When trying to access a property of an object, the property will not only be sought on the object but on the prototype of the object, the prototype of the prototype, and so on until either a property with a matching name is found or the end of the prototype chain is reached.

Javascriptのオブジェクト(の__proto__プロパティ)は、(継承元の?)prototypeオブジェクトを指している。オブジェクトのプロパティにアクセスするとき、自身だけでなく、その__proto__が指すもの、さらにその__proto__が指すもの、も探すよ。アクセスしようとしているプロパティが見つかるか、あるいはprototypeチェーンの終端(null)に行き着くまで探すよ。


↑の情報をもとに考えていく。

<script>

var C = function (name) {
    this.name = name;
};

console.log(`one:${Object.getPrototypeOf(C)}`);
console.log(`two:${C.__proto__===Object.getPrototypeOf(C)}`);
console.log(`three:${C.__proto__===Function.prototype}`);
console.log(`four:${C.__proto__===Object.prototype}`);


var o = {a: 1};

console.log(`one:${Object.getPrototypeOf(o)}`);
console.log(`two:${o.__proto__===Object.getPrototypeOf(o)}`);
console.log(`three:${o.__proto__===Function.prototype}`);
console.log(`four:${o.__proto__===Object.prototype}`);


</script>
zz_5.php:13 one:function () { [native code] }
zz_5.php:14 two:true
zz_5.php:15 three:true
zz_5.php:16 four:false
zz_5.php:21 one:[object Object]
zz_5.php:22 two:true
zz_5.php:23 three:false
zz_5.php:24 four:true

maeharin.hatenablog.comに書いてある通り、CにはFunctionオブジェクトがセットされる。

13行目:Object.getPrototypeOf(C)は、C.__proto__のこと。つまりFunction.prototype。

14行目:C.__proto__===Object.getPrototypeOf(C)}

これが__proto__,prototypeチェーンの定義ということなのだろう。なのでtrue。

15行目、16行目、maeharin.hatenablog.comに書いてある通りの結果といえる。

次に変数oに、オブジェクトリテラルを使って生成したオブジェクト(インスタンス)をセット。

21行目:Object.getPrototypeOf(o)

これはObject.prototypeのことなのだろう。

22行目:これもObject.getPrototypeOf(o)の定義のようなことなので当然true。
23行目、24行目:オブジェクトリテラルはObjectを基に生成されるので、o.__proto__がObject.prototypeを指す、ということか。C.__proto__がFunction.prototypeを指すのと同様、ということか。

ここまでは問題ない。次にObject.createメソッド。

<script>

var proto = {};
var obj = Object.create(proto);
console.log(Object.getPrototypeOf(obj) === proto); 
//true
</script>

Object.create()についてはこちら

新しいオブジェクトを生成する。どういうオブジェクトを生成するのか?

新しく生成するオブジェクトの__proto__プロパティが、(Object.create()の)引数に指定したオブジェクトを指す、そういうオブジェクトを生成する関数。

関数コンストラクタとnewでインスタンスを生成する場合、

let c1=new C();

をすると、c1.__proto__がC.prototypeを指すので、これは、

let c1=Object.create(C.prototype);

と同じこと。

<script>

var C = function (name) { 
	this.name = name; 
};

let c1=new C();
let c2=Object.create(C.prototype);

console.log(c1.__proto__===c2.__proto__);
//true

</script>

c1とc2は別のオブジェクトなのだが、どちらもCというFunctionオブジェクトを基に生成されているので上記のように

c1.__proto__===c2.__proto__(===C.prototype)
となる。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/create

javascriptの継承
// Shape - superclass
function Shape() {
  this.x = 0;
  this.y = 0;
}

// superclass method
Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.info('Shape moved.');
};

// Rectangle - subclass
function Rectangle() {
  Shape.call(this); // call super constructor.
}

// subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle; //If you don't set Object.prototype.constructor to Rectangle, 
                                            //it will take prototype.constructor of Shape (parent). 
                                           //To avoid that, we set the prototype.constructor to Rectangle (child).

var rect = new Rectangle();

console.log('Is rect an instance of Rectangle?',
  rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?',
  rect instanceof Shape); // true
rect.move(1, 1); // Outputs, 'Shape moved.'

 

コメントを残す

メールアドレスが公開されることはありません。