handler.setPrototypeOf()

handler.setPrototypeOf() メソッドは、オブジェクトの [[SetPrototypeOf]] 内部メソッドに対するトラップです。Object.setPrototypeOf() などの操作で使用されます。

試してみましょう

構文

js
new Proxy(target, {
  setPrototypeOf(target, prototype) {
  }
});

引数

次の引数は setPrototypeOf() メソッドに渡されます。 this はハンドラーにバインドされます。

target

ターゲットオブジェクトです。

prototype

オブジェクトの新しいプロトタイプ、または null です。

返値

setPrototypeOf() メソッドは [[Prototype]] の変更に成功したら true を返し、そうでない場合は false を返します。

解説

介入

このトラップは下記の操作に介入できます。

他にも、[[SetPrototypeOf]] 内部メソッドを呼び出すあらゆる操作に介入できます。

不変条件

以下の不変条件に違反している場合、プロキシーは TypeError を発生します。

  • target が拡張可能でない場合、引数の prototypeObject.getPrototypeOf(target) と同じ値でなければなりません。

オブジェクトに新しいプロトタイプを設定することを禁止したい場合は、ハンドラーの setPrototypeOf() メソッドで false を返したり、例外を発生させたりするようにすることができます。

アプローチ 1: false を返す

このアプローチでは、例外を発生させる変更操作は、それ自身で例外を生成する必要があります。

例えば、 Object.setPrototypeOf() は、それ自体が TypeError を発生させます。 Reflect.setPrototypeOf() のように、失敗しても通常は例外が発生しない操作で変更操作が行われた場合、例外は発生しません。

js
const handlerReturnsFalse = {
  setPrototypeOf(target, newProto) {
    return false;
  },
};

const newProto = {},
  target = {};

const p1 = new Proxy(target, handlerReturnsFalse);
Object.setPrototypeOf(p1, newProto); // throws a TypeError
Reflect.setPrototypeOf(p1, newProto); // returns false

アプローチ 2: 例外を発生

後者のアプローチでは、変更を試みるすべての操作で例外が発生します。このアプローチは、例外を発生しない操作でも失敗時に例外をは正させたい場合や、カスタムの例外値を発生させたい場合に最適です。

js
const handlerThrows = {
  setPrototypeOf(target, newProto) {
    throw new Error("custom error");
  },
};

const newProto = {},
  target = {};

const p2 = new Proxy(target, handlerThrows);
Object.setPrototypeOf(p2, newProto); // throws new Error("custom error")
Reflect.setPrototypeOf(p2, newProto); // throws new Error("custom error")

仕様書

Specification
ECMAScript Language Specification
# sec-proxy-object-internal-methods-and-internal-slots-setprototypeof-v

ブラウザーの互換性

BCD tables only load in the browser

関連情報