Movatterモバイル変換


[0]ホーム

URL:


MDN Web Docs

このページはコミュニティーの尽力で英語から翻訳されました。MDN Web Docs コミュニティーについてもっと知り、仲間になるにはこちらから。

Object.setPrototypeOf()

BaselineWidely available

Object.setPrototypeOf() 静的メソッドは、指定されたオブジェクトのプロトタイプ(つまり、内部の[[Prototype]] プロパティ)を、別のオブジェクトまたはnull に設定します。

警告:オブジェクトの[[Prototype]] を変更すると、最近の JavaScript エンジンがプロパティへのアクセスを最適化する方法の特質上、すべてのブラウザーや JavaScript エンジンで、操作がとても低速になります。さらに、プロトタイプを変更することの性能への影響は細かく広範囲にわたり、Object.setPrototypeOf(...) 文に費やされる時間だけではなく、[[Prototype]] が変更されたすべてのオブジェクトへのアクセスを持つ**すべて**のコードに影響する可能性があります。詳しくはJavaScript engine fundamentals: optimizing prototypes をお読みください。

この機能は言語の一部であるため、その機能の実装による負荷は (理念上は) エンジンの開発者によります。エンジンの開発者がこの問題に対処するまでの間、性能が気になる場合は、オブジェクトの[[Prototype]] を変更することは避けるべきです。代わりに、Object.create() を使用して必要な[[Prototype]] をもつオブジェクトを生成してください。

試してみましょう

const obj = {};const parent = { foo: "bar" };console.log(obj.foo);// Expected output: undefinedObject.setPrototypeOf(obj, parent);console.log(obj.foo);// Expected output: "bar"

構文

js
Object.setPrototypeOf(obj, prototype)

引数

obj

プロトタイプを設定するオブジェクト。

prototype

オブジェクトの新しいプロトタイプ(オブジェクトまたはnull)。

返値

指定されたオブジェクト。

例外

TypeError

以下のいずれかの場合に発生します。

  • 引数objundefined またはnull である場合。
  • 引数obj拡張不可能であるか、またはプロトタイプが不変のエキゾチックオブジェクト、例えばObject.prototypewindow 等の場合。ただし、新しいプロトタイプがobj の元のプロトタイプと同じ値である場合は、エラーは発生しません。
  • 引数prototype がオブジェクトまたはnull ではない場合。

解説

Object.setPrototypeOf() は、一般的にオブジェクトのプロトタイプを設定するための適切な方法と考えられています。非推奨のObject.prototype.__proto__ アクセサーの代わりに、常にこれを使用するべきでしょう。

もし引数obj がオブジェクト(例えば、数値、文字列など)でない場合、このメソッドは何もせず、オブジェクトに変換したり、プロトタイプを設定することなく、直接obj をプリミティブ値として返します。もしprototypeobj のプロトタイプと同じ値であれば、obj のプロトタイプが不変であってもTypeError は発生せずにobj が直接返されます。

セキュリティの観点から、プロトタイプが不変であるように設計された組み込みオブジェクトがあります。これにより、プロトタイプ汚染攻撃、特にブロキシー関連の攻撃を防ぐことができます。コア言語では、不変のプロトタイプを持つエキゾチックオブジェクトとしてObject.prototype のみを指定しており、そのプロトタイプは常にnull です。ブラウザーでは、windowlocation の 2 つがとても一般的な例です。

js
Object.isExtensible(Object.prototype); // true。プロパティを追加できるObject.setPrototypeOf(Object.prototype, {}); // TypeError: 不変のプロトタイプオブジェクト '#<Object>' にプロトタイプを設定することはできないObject.setPrototypeOf(Object.prototype, null); // エラーなし。 `Object.prototype` のプロパティがすでに `null` であるため

Object.setPrototypeOf() を使った擬似クラス継承

クラスを使用した JS の継承です。

js
class Human {}class SuperHero extends Human {}const superMan = new SuperHero();

しかし、class を使わずにサブクラスを実装したい場合は、次のようにします。

js
function Human(name, level) {  this.name = name;  this.level = level;}function SuperHero(name, level) {  Human.call(this, name, level);}Object.setPrototypeOf(SuperHero.prototype, Human.prototype);// `SuperHero.prototype` の `[[Prototype]]` を `Human.prototype` に設定// プロトタイプのインスタンスチェーンを設定するためHuman.prototype.speak = function () {  return `${this.name} says hello.`;};SuperHero.prototype.fly = function () {  return `${this.name} is flying.`;};const superMan = new SuperHero("Clark Kent", 1);console.log(superMan.fly());console.log(superMan.speak());

上記のような古典的継承(クラスによる継承)と擬似古典的継承(コンストラクターのprototype プロパティによる継承)の類似性については、継承チェーンで述べられています。

関数コンストラクターのprototype プロパティは書き込み可能なので、Object.create() で作成した新しいオブジェクトに再割り当てすることで、同じ継承連鎖を実現できます。create() を使用する際には、constructor プロパティを再度追加することを忘れないようにするなどの注意点があります。

以下の例でもクラスを使用していますが、SuperHeroextends を使用せずに、代わりにsetPrototypeOf() を使用してHuman を継承しています。

警告:extends の代わりにsetPrototypeOf() を使うことは、パフォーマンスや可読性の点からお勧めできません。

js
class Human {}class SuperHero {}// 継承プロパティを設定Object.setPrototypeOf(SuperHero.prototype, Human.prototype);// 静的プロパティをフックObject.setPrototypeOf(SuperHero, Human);const superMan = new SuperHero();

extends を使わないサブクラス化は、ES-6 subclassing で触れられています。

仕様書

Specification
ECMAScript® 2026 Language Specification
# sec-object.setprototypeof

ブラウザーの互換性

関連情報

Help improve MDN

Learn how to contribute.

This page was last modified on byMDN contributors.


[8]ページ先頭

©2009-2025 Movatter.jp