Object.creat()
を使うと、[[Prototype]]
を指定した上で、オブジェクトを生成できる。
リテラルで生成したオブジェクトの[[Prototype]]
はObject.prototype
になるが、Object.creat()
を使えば、任意のオブジェクトを[[Prototype]]
に設定できる。
Object.creat()
の第一引数にプロトタイプオブジェクトを渡し、第二引数にプロパティディスクリプタを渡すことで、オブジェクトを生成できる。
第二引数は省略可能。
var person1 = { sayName: function(){ console.log(this.name); } }; // person1のプロトタイプオブジェクトはObject.prototype console.log(person1.__proto__ === Object.prototype); // true var person2 = Object.create(person1, { name:{ value: 'Tom', writable: true, enumerable: true, configurable: true } }); // person2のプロトタイプオブジェクトはperson1 console.log(person2.__proto__ === person1); // true person2.sayName(); // Tom
プロトタイプチェーン
プロパティを読み込もうとした際、まず、オブジェクト自身がそのプロパティを持っていないか確認する。
持っていなかった場合、そのオブジェクトの[[Prototype]]
が参照しているプロトタイプオブジェクトの中から、同名のプロパティがないかを検索する。
それでも見つからなかった場合、プロトタイプオブジェクトの[[Prototype]]
の中を検索する。
以降、プロパティが見つかるか、[[Prototype]]
がnull
を返すまで、このサイクルを繰り返す。
このサイクルを、プロトタイプチェーンと呼ぶ。
通常、Object.prototype
はnull
なので、そこがプロトタイプチェーンの終端となることが多い。
var person1 = { sayHello: function(){ console.log('Hello'); } }; var person2 = Object.create(person1); person2.sayHello(); // Hello console.log(person2.hasOwnProperty('sayHello')); // false console.log(person2.__proto__ === person1); // true console.log(person1.hasOwnProperty('sayHello')); // true // person2のプロトタイプであるperson1がsayHelloを持っているため、実行される console.log(person2.toString()); // [object Object] console.log(person2.hasOwnProperty('toString')); // false console.log(person1.hasOwnProperty('toString')); // false console.log(person1.__proto__ === Object.prototype); // true console.log(Object.prototype.hasOwnProperty('toString')); // true // person2のプロトタイプ(person1)のプロトタイプであるObject.prototypeがtoStringを持っているため、実行される console.log(person2.__proto__ === person1); // true console.log(person2.__proto__.__proto__ === Object.prototype); // true console.log(person2.__proto__.__proto__.__proto__ === null); // true // Object.prototypeの[[Prototype]]はnull