Object.setPrototypeOf() メソッドは、指定されたオブジェクトのプロトタイプ (つまり、内部の [[Prototype]] プロパティ) を、別のオブジェクトまたは null に設定します。
警告: オブジェクトの [[Prototype]] を変更すると、 最近の JavaScript エンジンがプロパティへのアクセスを最適化する方法の特質上、すべてのブラウザーや JavaScript エンジンで、操作がとても低速になります。さらに、プロトタイプを変更することの性能への影響は細かく広範囲にわたり、 Object.setPrototypeOf(...) 文に費やされる時間だけではなく、 [[Prototype]] が変更されたすべてのオブジェクトへのアクセスを持つすべてのコードに影響する可能性があります。
この機能は言語の一部であるため、その機能の実装による負荷は (理念上は) エンジンの開発者によります。エンジンの開発者がこの問題に対処するまでの間、性能が気になる場合は、オブジェクトの [[Prototype]] を変更することは避けるべきです。代わりに、 Object.create() を使用して必要な [[Prototype]] をもつオブジェクトを生成してください。
構文
Object.setPrototypeOf(obj, prototype)
引数
obj- プロトタイプとして設定されるオブジェクト。
prototype- オブジェクトの新しいプロトタイプ (オブジェクトまたは
null)。
返値
指定されたオブジェクト。
説明
[[Prototype]] が変更されるオブジェクトが Object.isExtensible() に応じて拡張不可の場合、 TypeError 例外を投げます。prototype 引数がオブジェクトまたは null ではない場合(つまり、数値、文字列、boolean、 undefined のいずれか)、何もしません。さもなければ、このメソッドは obj の [[Prototype]] を新しい値に変更します。
Object.setPrototypeOf() は、 ECMAScript 2015 仕様書にあります。一般的には、オブジェクトのプロトタイプを設定するための適切な方法と考えられています。もっと物議を醸すObject.prototype.__proto__ プロパティがあります。
例
var dict = Object.setPrototypeOf({}, null);
ポリフィル
Object.setPrototypeOf が利用できない場合、より古い Object.prototype.__proto__ プロパティを使って、簡単に定義することができます。
if (!Object.setPrototypeOf) {
// Chrome および FireFox で動作しますが、 IE では動作しません
Object.prototype.setPrototypeOf = function(obj, proto) {
if(obj.__proto__) {
obj.__proto__ = proto;
return obj;
} else {
// Object.create(null) のプロトタイプを返したい場合
var Fn = function() {
for (var key in obj) {
Object.defineProperty(this, key, {
value: obj[key],
});
}
};
Fn.prototype = proto;
return new Fn();
}
}
}
プロトタイプチェーンの追加
Object.getPrototypeOf() と Object.prototype.__proto__ の組み合わせによってプロトタイプチェーン全体を新しいプロトタイプオブジェクトに追加できます。
/**
*** Object.appendChain(@object, @prototype)
*
* Appends the first non-native prototype of a chain to a new prototype.
* Returns @object (if it was a primitive value it will transformed into an object).
*
*** Object.appendChain(@object [, "@arg_name_1", "@arg_name_2", "@arg_name_3", "..."], "@function_body")
*** Object.appendChain(@object [, "@arg_name_1, @arg_name_2, @arg_name_3, ..."], "@function_body")
*
* Appends the first non-native prototype of a chain to the native Function.prototype object, then appends a
* new Function(["@arg"(s)], "@function_body") to that chain.
* Returns the function.
*
**/
Object.appendChain = function(oChain, oProto) {
if (arguments.length < 2) {
throw new TypeError('Object.appendChain - 引数が足りません');
}
if (typeof oProto !== 'object' && typeof oProto !== 'string') {
throw new TypeError('Object.appendChain の第二引数は object か string でなければなりません');
}
var oNewProto = oProto,
oReturn = o2nd = oLast = oChain instanceof this ? oChain : new oChain.constructor(oChain);
for (var o1st = this.getPrototypeOf(o2nd);
o1st !== Object.prototype && o1st !== Function.prototype;
o1st = this.getPrototypeOf(o2nd)
) {
o2nd = o1st;
}
if (oProto.constructor === String) {
oNewProto = Function.prototype;
oReturn = Function.apply(null, Array.prototype.slice.call(arguments, 1));
this.setPrototypeOf(oReturn, oLast);
}
this.setPrototypeOf(o2nd, oNewProto);
return oReturn;
}
使い方
最初の例: チェーンをプロトタイプに追加する
function Mammal() {
this.isMammal = 'yes';
}
function MammalSpecies(sMammalSpecies) {
this.species = sMammalSpecies;
}
MammalSpecies.prototype = new Mammal();
MammalSpecies.prototype.constructor = MammalSpecies;
var oCat = new MammalSpecies('Felis');
console.log(oCat.isMammal); // 'yes'
function Animal() {
this.breathing = 'yes';
}
Object.appendChain(oCat, new Animal());
console.log(oCat.breathing); // 'yes'
二番目の例: そのコンストラクタのインスタンスにプリミティブ値を変換し、プロトタイプにそのチェーンを追加する
function MySymbol() {
this.isSymbol = 'yes';
}
var nPrime = 17;
console.log(typeof nPrime); // 'number'
var oPrime = Object.appendChain(nPrime, new MySymbol());
console.log(oPrime); // '17'
console.log(oPrime.isSymbol); // 'yes'
console.log(typeof oPrime); // 'object'
三番目の例: チェーンを Function.prototype オブジェクトに追加し、新しい関数をそのチェーンに追加する
function Person(sName) {
this.identity = sName;
}
var george = Object.appendChain(new Person('George'),
'console.log("Hello guys!!");');
console.log(george.identity); // 'George'
george(); // 'Hello guys!!'
仕様書
| 仕様書 | 状態 | 備考 |
|---|---|---|
| ECMAScript (ECMA-262) Object.setPrototypeOf の定義 |
現行の標準 | |
| ECMAScript 2015 (6th Edition, ECMA-262) Object.setPrototypeOf の定義 |
標準 | 初回定義 |
ブラウザーの互換性
| デスクトップ | モバイル | サーバー | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
setPrototypeOf | Chrome 完全対応 34 | Edge 完全対応 12 | Firefox 完全対応 31 | IE 完全対応 11 | Opera 完全対応 21 | Safari 完全対応 9 | WebView Android 完全対応 37 | Chrome Android 完全対応 34 | Firefox Android 完全対応 31 | Opera Android 完全対応 21 | Safari iOS 完全対応 9 | Samsung Internet Android 完全対応 2.0 | nodejs 完全対応 0.12 |
凡例
- 完全対応
- 完全対応