blog

オブジェクトの作成、プロトタイプの連鎖、継承メソッド

作成されたオブジェクト 1.リテラル 2.コンストラクタ・メソッドで作成されたオブジェクト、プロトタイプ・オブジェクトがパラメータ 3つの作成方法の結果を示します:プロトタイプ・チェイン 1.コンスト...

Aug 11, 2020 · 4 min. read
シェア

オブジェクトの生成方法

リテラル

var o1 = { name: 'o1' };
var o2 = new Object({ name: 'o2' });

コンストラクタを介して

var M = function(name) { this.name = name;}
var o3 = new M('o3');

Object.create()

プロトタイプ・オブジェクトを引数として、Object.create(p)メソッドを使用して作成されたオブジェクト。
var p = { name: 'o4' };
var o4 = Object.create(p);

3つの作成方法の結果を示します:

![]

プロトタイプチェーン

コンストラクタ、インスタンス、プロトタイプオブジェクトの関係

var M = function(name) { 
 this.name = name;
}
var o3 = new M('o3');
console.log(o3);
console.log(o3.constructor === M); // true
console.log(o3.__proto__ === M.prototype); // true
console.log(M.prototype.constructor === M) // true

役割:プロトタイプの検出

原則:インスタンスオブジェクトの__proto__とコンストラクタのプロトタイプが同じ参照かどうかを判断します。

var M = function(name) { this.name = name; } var o3 = new M('o3'); console.log(o3 instanceof M); // true console.log(o3 instanceof Object); // true console.log(o3.__proto__ === M.prototype); // true console.log(M.prototype.__proto__ === Object.prototype); // true

constructor

役割: オブジェクトをインスタンス化したのが誰なのかを区別します。

var M = function(name) {
 this.name = name;
}
var o3 = new M('o3');
console.log(o3.constructor === M); // true
console.log(o3.constructor === Object); // false

クラス宣言

/** * クラス宣言*/function Animal() { this.name = 'name';
}/** * ES6プロトタイプ・オブジェクトはクラス宣言のパラメータである。*/class Animal2 { constructor() { this.name = 'name'; }}
/** * インスタンス化される*/
console.log(new Animal(), new Animal2())

クラス継承

コンストラクタによる継承

原則:Parent1 の this ポイントを変更します。

欠点:Parent1プロトタイプチェーンのメソッドはChild1には継承されません。

/** 
 * コンストラクタによる継承
 * 原則:Parent1の thisを次のように変更する。, 
 * デメリット:Parent1のプロトタイプチェーンのメソッドはChild1に継承されない。
 */
function Parent1() {
 this.name = 'Parent1';
}
Parent1.prototype.say = function() {};
function Child1() {
 Parent1.call(this); // apply this "を
 this.type = 'Child1';
}
var s1 = new Child1();
console.log(s1); // Child1 {name: "Parent1", type: "Child1"}
console.log(s1.constructor === Parent1) // true

プロトタイプチェーンによる継承

デメリット:2つのオブジェクトをインスタンス化し、片方を変更すると、もう片方も変更されます。

理由:プロトタイプチェーンのプロトタイプオブジェクトが共有されているため、s2_1.proto = s2_2.proto

/** 
 * プロトタイプチェーンによる継承
 * デメリット:2つのオブジェクトがインスタンス化され、片方が変更されると、もう片方も変更される。
 * 理由:プロトタイプオブジェクトはプロトタイプチェーンで共有されるため。,s2_1.__proto__ = s2_2.__proto__
 */
function Parent2() {
 this.name = 'Parent2';
 this.play = [1, 2, 3];
}
function Child2() {
 this.type = 'Child2';
}
Child2.prototype = new Parent2();
var s2_1 = new Child2();
var s2_2 = new Child2();
s2_1.play.push(4);
console.log('s2_1(push 4):', s2_1.play); // s2_1(push 4): [1, 2, 3, 4]
console.log('s2_2:', s2_2.play); // s2_1: [1, 2, 3, 4]
console.log(s2_1.__proto__ === Child2.prototype, Child2.prototype.__proto__ === Parent2.prototype); // true true
console.log(s2_1.constructor === Parent2); // trueconsole.log(s2_1.__proto__ === s2_2.__proto__); // true

コンビナトリアルアプローチ

欠点:

サブクラスをインスタンス化するとき、親クラスは次の 2 つの処理を行います。

オブジェクトは親クラスによってインスタンス化されます。

/**
 * コンビナトリアルアプローチ
 *  
    1.  子クラスをインスタンス化するとき、親クラスは以下の2つの処理を行う。
 * 
    2.  オブジェクトは親クラスによってインスタンス化される
 */
function Parent3() {
 this.name = 'Parent3';
 this.play = [1, 2, 3];
}
function Child3() {
 Parent3.call(this); // apply this "を
 this.type = 'Child3';
}
Child3.prototype = new Parent3();
var s3_1 = new Child3();
var s3_2 = new Child3();
s3_1.play.push(4);
console.log('s3_1(push 4):', s3_1.play); // s3_1(push 4): [1, 2, 3, 4]
console.log('s3_2:', s3_2.play); // s3_1: [1, 2, 3]

複合継承最適化アプローチ1

まだ存在する欠点:オブジェクトは親クラスによってインスタンス化されます。

/**
 * 組み合わせ継承の最適化 1
 * デメリット:オブジェクトは親クラスによってインスタンス化される
 */
function Parent4() {
 this.name = 'Parent4';
 this.play = [1, 2, 3];
}
function Child4() {
 Parent4.call(this); // apply this "を
 this.type = 'Child4';
}
Child4.prototype = Parent4.prototype;
var s4 = new Child4();
s4.play.push(4);
console.log('s4:', s4 instanceof Child4, s4 instanceof Parent4);
// オブジェクトが親クラスによってインスタンス化されたのか、子クラスによってインスタンス化されたのかを区別する方法
// コンストラクタ属性を使用する
console.log(s4.constructor == Parent4);

複合継承最適化アプローチ2

注:Object.create(Parent5.prototype) オブジェクトを生成 プロトタイプオブジェクトがパラメータです。

/** * 組み合わせ継承の最適化2 * Object.create(Parent5.prototype) 生成されたオブジェクト プロトタイプ・オブジェクトが パラメータである */ function Parent5() { this.name = 'Parent5'; this.play = [1, 2, 3]; } function Child5() { Parent5.call(this); // apply this "を this.type = 'Child5'; } Child5.prototype = Object.create(Parent5.prototype); Child5.prototype.constructor = Child5; var s5 = new Child5(); console.log('s5:', s5 instanceof Child5); // true true // オブジェクトが親クラスによってインスタンス化されたのか、子クラスによってインスタンス化されたのかを区別する方法 // コンストラクタ属性を使用する console.log(s5.constructor == Parent5); // false console.log(s5); // Child5 {name: "Parent5", play: Array(3), type: "Child5"}

Read next

ES6クイックスタート

JSON文字列を受け取り、オブジェクトに変換します。 オブジェクトを受け取り、JSON文字列に変換します。 for ... 配列の添え字キーf...

Aug 10, 2020 · 11 min read

Javaスレッド割り込みの秘密

Aug 10, 2020 · 12 min read

EventBusソースコード解析

Aug 10, 2020 · 17 min read

Vuexの使用経験

Aug 10, 2020 · 7 min read