オブジェクトの生成方法
リテラル
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"}




