recursal/MDN huggingface dataset:
Atomics.xor()
=============

**`Atomics.xor()`** 静态方法会将给定的值与数组指定位置上的值进行按位异或运算，并返回该位置的旧值。此原子操作保证在修改后的值写回之前不会发生其他写操作。

尝试一下
----

语法
--


```js
Atomics.xor(typedArray, index, value)
```

### 参数

`typedArray`

一个整数类型数组。`Int8Array`、`Uint8Array`、`Int16Array`、`Uint16Array`、`Int32Array`、`Uint32Array`、`BigInt64Array` 或 `BigUint64Array` (en-US) 之一。

`index`

`typedArray` 中要进行按位异或运算的位置。

`value`

要进行按位异或运算的值。

### 返回值

给定位置的旧值（`typedArray[index]`）。

### 异常

`TypeError`

如果 `typedArray` 不是允许的整数类型数组之一，则抛出该异常。

`RangeError`

如果 `index` 超出 `typedArray` 的范围，则抛出该异常。

描述
--

当 `a` 和 `b` 不同时，按位异或运算结果为 1。异或运算的真值表如下：

| `a` | `b` | `a ^ b` |
| --- | --- | --- |
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |

例如，`5 ^ 1` 按位异或运算的结果是 `0100`，也就是十进制的 4。
```

5  0101
1  0001
   ----

4  0100
```

### 使用 xor()


```js
const sab = new SharedArrayBuffer(1024);
const ta = new Uint8Array(sab);
ta[0] = 5;

Atomics.xor(ta, 0, 1); // 返回 5，即旧的值
Atomics.load(ta, 0); // 4
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-atomics.xor |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `Atomics`
* `Atomics.and()`
* `Atomics.or()`
Atomics.or()
============

**`Atomics.or()`** 静态方法会将给定的值与数组指定位置上的值进行按位或运算，并返回该位置的旧值。此原子操作保证在修改后的值写回之前不会发生其他写操作。

尝试一下
----

语法
--


```js
Atomics.or(typedArray, index, value)
```

### 参数

`typedArray`

一个整数类型数组。`Int8Array`、`Uint8Array`、`Int16Array`、`Uint16Array`、`Int32Array`、`Uint32Array`、`BigInt64Array` 或 `BigUint64Array` (en-US) 之一。

`index`

`typedArray` 中要进行按位或运算的位置。

`value`

要进行按位或运算的值。

### 返回值

给定位置的旧值（`typedArray[index]`）。

### 异常

`TypeError`

如果 `typedArray` 不是允许的整数类型数组之一，则抛出该异常。

`RangeError`

如果 `index` 超出 `typedArray` 的范围，则抛出该异常。

描述
--

当 `a` 或 `b` 为 1 时，按位或运算结果为 1。或运算的真值表如下：

| `a` | `b` | `a | b` |
| --- | --- | --- |
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |

例如， `5 | 1` 按位或运算的结果是 `0101` ，也就是十进制的 5：
```

5  0101
1  0001
   ----

5  0101
```

示例
--

### 使用 or()


```js
const sab = new SharedArrayBuffer(1024);
const ta = new Uint8Array(sab);
ta[0] = 2;

Atomics.or(ta, 0, 1); // 返回 2，即旧的值
Atomics.load(ta, 0); // 3
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-atomics.or |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `Atomics`
* `Atomics.and()`
* `Atomics.xor()`
Proxy.revocable()
=================

**`Proxy.revocable()`** 方法可以用来创建一个可撤销的代理对象。

语法
--
```

Proxy.revocable(target, handler);
```


`target`

将用 `Proxy` 封装的目标对象。可以是任何类型的对象，包括原生数组，函数，甚至可以是另外一个代理对象。

`handler`

一个对象，其属性是一批可选的函数，这些函数定义了对应的操作被执行时代理的行为。

### 返回值

返回一个包含了代理对象本身和它的撤销方法的可撤销 `Proxy` 对象。

描述
--

该方法的返回值是一个对象，其结构为： `{"proxy": proxy, "revoke": revoke}`，其中：

`proxy`

表示新生成的代理对象本身，和用一般方式 `new Proxy(target, handler)` 创建的代理对象没什么不同，只是它可以被撤销掉。

`revoke`

撤销方法，调用的时候不需要加任何参数，就可以撤销掉和它一起生成的那个代理对象。

一旦某个代理对象被撤销，它将变得几乎完全不可调用，在它身上执行任何的**可代理操作**都会抛出 `TypeError` 异常（注意，可代理操作一共有 `14 种`，执行这 14 种操作以外的操作不会抛出异常）。一旦被撤销，这个代理对象便不可能被直接恢复到原来的状态，同时和它关联的**目标对象**以及**处理器对象**都有可能被垃圾回收掉。再次调用撤销方法 `revoke()` 则不会有任何效果，但也不会报错。

示例
--


```js
var revocable = Proxy.revocable(
  {},
  {
    get(target, name) {
      return "[[" + name + "]]";
    },
  },
);
var proxy = revocable.proxy;
proxy.foo; // "[[foo]]"

revocable.revoke();

console.log(proxy.foo); // 抛出 TypeError
proxy.foo = 1; // 还是 TypeError
delete proxy.foo; // 又是 TypeError
typeof proxy; // "object"，因为 typeof 不属于可代理操作
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-proxy.revocable |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `Proxy`
Proxy() 构造器
===========

**`Proxy()`** 构造器用来创建 `Proxy` 对象。语法
--


```js
new Proxy(target, handler)
```

### 参数

`target`

`Proxy` 会对 target 对象进行包装。它可以是任何类型的对象，包括内置的数组，函数甚至是另一个代理对象。

`handler`

它是一个对象，它的属性提供了某些操作发生时所对应的处理函数。

描述
--

我们可以使用 `Proxy()` 构造器来创建一个新的 `Proxy` 对象。构造器接收两个主要参数：

* `target` 被代理的对象
* `handler` 被代理对象上的自定义行为

一个空的 `handler` 参数将会创建一个与被代理对象行为几乎完全相同的代理对象。通过在 `handler` 对象上定义一组处理函数，你可以自定义被代理对象的一些特定行为。例如，通过定义 `get()` 你就可以自定义被代理对象的属性访问器。

### 处理函数

本节列出了所有你可以自定义的处理函数。处理函数有时候也被成为“劫持”（traps），这是由于它们会对底层被代理对象的调用进行劫持。

`handler.apply()`

函数调用劫持。

`handler.construct()`

`new` 操作符劫持

`handler.defineProperty()`

`Object.defineProperty`调用劫持。

`handler.deleteProperty()`

`delete` 操作符劫持。

`handler.get()`

获取属性值劫持。

`handler.getOwnPropertyDescriptor()`

`Object.getOwnPropertyDescriptor` 调用劫持。

`handler.getPrototypeOf()`

`Object.getPrototypeOf`调用劫持。

`handler.has()`

`in` 操作符劫持。

`handler.isExtensible()`

`Object.isExtensible`调用劫持。

`handler.ownKeys()`

`Object.getOwnPropertyNames` 和`Object.getOwnPropertySymbols`调用劫持。

`handler.preventExtensions()`

`Object.preventExtensions`调用劫持。

`handler.set()`

设置属性值劫持。

`handler.setPrototypeOf()`

`Object.setPrototypeOf`调用劫持。

示例
--

### 选择性代理属性访问器

本例中，被代理对象有两个属性： `notProxied` 和 `proxied` 。我们定义了一个处理函数，它为 `proxied` 属性返回一个不同的值，而其他属性返回原值。


```js
const target = {
  notProxied: "original value",
  proxied: "original value",
};

const handler = {
  get: function (target, prop, receiver) {
    if (prop === "proxied") {
      return "replaced value";
    }
    return Reflect.get(...arguments);
  },
};

const proxy = new Proxy(target, handler);

console.log(proxy.notProxied); // "original value"
console.log(proxy.proxied); // "replaced value"
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-proxy-constructor |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* 元编程指南
* `Reflect`
handler.getPrototypeOf()
========================

**`handler.getPrototypeOf()`** 是一个代理（Proxy）方法，当读取代理对象的原型时，该方法就会被调用。

尝试一下
----

语法
--


```js
const p = new Proxy(obj, {
  getPrototypeOf(target) {
  ...
  }
});
```

### 参数

当 `getPrototypeOf` 方法被调用时，`this` 指向的是它所属的处理器对象。

`target`

被代理的目标对象。

### 返回值

`getPrototypeOf` 方法的返回值必须是一个对象或者 `null`。

描述
--

在 JavaScript 中，下面这五种操作（方法/属性/运算符）可以触发 JS 引擎读取一个对象的原型，也就是可以触发 `getPrototypeOf()` 代理方法的运行：

* `Object.getPrototypeOf()`
* `Reflect.getPrototypeOf()`
* `Object.prototype.__proto__`
* `Object.prototype.isPrototypeOf()`
* `instanceof`

如果遇到了下面两种情况，JS 引擎会抛出 `TypeError` 异常：

* `getPrototypeOf()` 方法返回的不是对象也不是 `null`。
* 目标对象是不可扩展的，且 `getPrototypeOf()` 方法返回的原型不是目标对象本身的原型。
示例
--

### 基本用法


```js
var obj = {};
var proto = {};
var handler = {
  getPrototypeOf(target) {
    console.log(target === obj); // true
    console.log(this === handler); // true
    return proto;
  },
};

var p = new Proxy(obj, handler);
console.log(Object.getPrototypeOf(p) === proto); // true
```

### 5 种触发 getPrototypeOf 代理方法的方式


```js
var obj = {};
var p = new Proxy(obj, {
  getPrototypeOf(target) {
    return Array.prototype;
  },
});
console.log(
  Object.getPrototypeOf(p) === Array.prototype, // true
  Reflect.getPrototypeOf(p) === Array.prototype, // true
  p.__proto__ === Array.prototype, // true
  Array.prototype.isPrototypeOf(p), // true
  p instanceof Array, // true
);
```

### 两种情况下的异常


```js
var obj = {};
var p = new Proxy(obj, {
  getPrototypeOf(target) {
    return "foo";
  },
});
Object.getPrototypeOf(p); // TypeError: "foo" is not an object or null

var obj = Object.preventExtensions({});
var p = new Proxy(obj, {
  getPrototypeOf(target) {
    return {};
  },
});
Object.getPrototypeOf(p); // TypeError: expected same prototype value
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-proxy-object-internal-methods-and-internal-slots-getprototypeof |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `Proxy`
* `handler` (en-US)
* `Object.getPrototypeOf()`
* `Reflect.getPrototypeOf()`
handler.deleteProperty()
========================

**`handler.deleteProperty()`** 方法用于拦截对对象属性的 `delete` 操作。

语法
--


```js
var p = new Proxy(target, {
  deleteProperty: function (target, property) {},
});
```

### 参数

`deleteProperty` 方法将会接受以下参数。`this` 被绑定在 handler 上。

`target`

目标对象。

`property`

待删除的属性名。

### 返回值

`deleteProperty` 必须返回一个 `Boolean` 类型的值，表示了该属性是否被成功删除。

描述
--

**`handler.deleteProperty()`** 方法可以拦截 `delete` 操作。

### 拦截

该方法会拦截以下操作：

* 删除属性：`delete proxy[foo]` 和 `delete proxy.foo`
* `Reflect.deleteProperty()`
### 不变量

如果违背了以下不变量，proxy 将会抛出一个 `TypeError`:

* 如果目标对象的属性是不可配置的，那么该属性不能被删除。
示例
--

以下代码演示了对 `delete` 操作的拦截。


```js
var p = new Proxy(
  {},
  {
    deleteProperty: function (target, prop) {
      console.log("called: " + prop);
      return true;
    },
  },
);

delete p.a; // "called: a"
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-proxy-object-internal-methods-and-internal-slots-delete-p |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

另见
--

* `Proxy`
* `handler` (en-US)
* `delete` 操作符
* `Reflect.deleteProperty()`
handler.getOwnPropertyDescriptor()
==================================

**`handler.getOwnPropertyDescriptor()`** 方法是 `Object.getOwnPropertyDescriptor()` 的钩子。

语法
--


```js
var p = new Proxy(target, {
  getOwnPropertyDescriptor: function (target, prop) {},
});
```

### 参数

`下列参数会被传入 getOwnPropertyDescriptor` 方法中。这是绑定到 handler 上。

`target`

目标对象。

`prop`

返回属性名称的描述。

### 返回值

`getOwnPropertyDescriptor` 方法必须返回一个 object 或 `undefined`。

描述
--

**`handler.getOwnPropertyDescriptor()`** 方法是 `Object.getOwnPropertyDescriptor()` 的陷阱。

### 拦截

这个陷阱可以拦截这些操作：

* `Object.getOwnPropertyDescriptor()`
* `Reflect.getOwnPropertyDescriptor()`
### 不变量

如果下列不变量被违反，代理将抛出一个 `TypeError`：

* `getOwnPropertyDescriptor` 必须返回一个 object 或 `undefined`。
* 如果属性作为目标对象的不可配置的属性存在，则该属性无法报告为不存在。
* 如果属性作为目标对象的属性存在，并且目标对象不可扩展，则该属性无法报告为不存在。
* 如果属性不存在作为目标对象的属性，并且目标对象不可扩展，则不能将其报告为存在。
* 属性不能被报告为不可配置，如果它不作为目标对象的自身属性存在，或者作为目标对象的可配置的属性存在。
* Object.getOwnPropertyDescriptor（target）的结果可以使用 Object.defineProperty 应用于目标对象，也不会抛出异常。
示例
--

以下是 `Object.getOwnPropertyDescriptor()` 的代码陷阱：


```js
var p = new Proxy(
  { a: 20 },
  {
    getOwnPropertyDescriptor: function (target, prop) {
      console.log("called: " + prop);
      return { configurable: true, enumerable: true, value: 10 };
    },
  },
);

console.log(Object.getOwnPropertyDescriptor(p, "a").value); // "called: a"; output 10
```


以下代码则违反了不变量。


```js
var obj = { a: 10 };
Object.preventExtensions(obj);
var p = new Proxy(obj, {
  getOwnPropertyDescriptor: function (target, prop) {
    return undefined;
  },
});

Object.getOwnPropertyDescriptor(p, "a"); // TypeError is thrown
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-proxy-object-internal-methods-and-internal-slots-getownproperty-p |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `Proxy`
* `handler` (en-US)
* `Object.getOwnPropertyDescriptor()`
* `Reflect.getOwnPropertyDescriptor()`
handler.ownKeys()
=================

**`handler.ownKeys()`** 方法用于拦截 `Reflect.ownKeys()`.

尝试一下
----

语法
--


```js
var p = new Proxy(target, {
  ownKeys: function (target) {},
});
```

### 参数

下面的参数被传递给 ownKeys。`this` 被绑定在 `handler` 上。

`target`

目标对象。

### 返回值

`ownKeys` 方法必须返回一个可枚举对象。

描述
--

**`handler.ownKeys()`** 方法用于拦截 `Reflect.ownKeys()`.

### 拦截

该拦截器可以拦截以下操作::

* `Object.getOwnPropertyNames()`
* `Object.getOwnPropertySymbols()`
* `Object.keys()`
* `Reflect.ownKeys()`
### 约束

如果违反了下面的约束，proxy 将抛出错误 `TypeError`:

* `ownKeys` 的结果必须是一个数组。
* 数组的元素类型要么是一个 `String` ，要么是一个 `Symbol`.
* 结果列表必须包含目标对象的所有不可配置（non-configurable）、自有（own）属性的 key.
* 如果目标对象不可扩展，那么结果列表必须包含目标对象的所有自有（own）属性的 key，不能有其他值。
示例
--

下面的代码拦截 `Object.getOwnPropertyNames()`.


```js
var p = new Proxy(
  {},
  {
    ownKeys: function (target) {
      console.log("called");
      return ["a", "b", "c"];
    },
  },
);

console.log(Object.getOwnPropertyNames(p)); // "called"; outputs [ 'a', 'b', 'c' ]
```


下面的代码违反了约定


```js
var obj = {};
Object.defineProperty(obj, "a", {
  configurable: false,
  enumerable: true,
  value: 10,
});

var p = new Proxy(obj, {
  ownKeys: function (target) {
    return [123, 12.5, true, false, undefined, null, {}, []];
  },
});

console.log(Object.getOwnPropertyNames(p));

// TypeError: proxy [[OwnPropertyKeys]] 必须返回一个数组
// 数组元素类型只能是 String 或 Symbol
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

另见
--

* `Proxy`
* `handler` (en-US)
* `Object.getOwnPropertyNames()`
* `Reflect.ownKeys()`
handler.defineProperty()
========================

**`handler.defineProperty()`** 用于拦截对象的 `Object.defineProperty()` 操作。

语法
--


```js
var p = new Proxy(target, {
  defineProperty: function (target, property, descriptor) {},
});
```

### 参数

下列参数将会被传递给 `defineProperty` 方法。`this` 绑定在 handler 对象上。

`target`

目标对象。

`property`

待检索其描述的属性名。

`descriptor`

待定义或修改的属性的描述符。

### 返回值

`defineProperty` 方法必须以一个 `Boolean` 返回，表示定义该属性的操作成功与否。

描述
--

**`handler.defineProperty()`** 用于拦截对对象的 `Object.defineProperty()` 操作。

### 拦截

该方法会拦截目标对象的以下操作：

* `Object.defineProperty()`
* `Reflect.defineProperty()`
* `proxy.property='value'`
### 不变量

如果违背了以下的不变量，proxy 会抛出 `TypeError`:

* 如果目标对象不可扩展，将不能添加属性。
* 不能添加或者修改一个属性为不可配置的，如果它不作为一个目标对象的不可配置的属性存在的话。
* 如果目标对象存在一个对应的可配置属性，这个属性可能不会是不可配置的。
* 如果一个属性在目标对象中存在对应的属性，那么 `Object.defineProperty(target, prop, descriptor)` 将不会抛出异常。
* 在严格模式下，`false` 作为 `handler.defineProperty` 方法的返回值的话将会抛出 `TypeError` 异常。
示例
--

以下代码演示如何拦截对目标对象的 `Object.defineProperty()` 操作。


```js
var p = new Proxy(
  {},
  {
    defineProperty: function (target, prop, descriptor) {
      console.log("called: " + prop);
      return true;
    },
  },
);

var desc = { configurable: true, enumerable: true, value: 10 };
Object.defineProperty(p, "a", desc); // "called: a"
```


当调用 `Object.defineProperty()` 或者 `Reflect.defineProperty()`，传递给 `defineProperty` 的 `descriptor` 有一个限制 - 只有以下属性才有用，非标准的属性将会被无视：

* `enumerable`
* `configurable`
* `writable`
* `value`
* `get`
* `set`


```js
var p = new Proxy(
  {},
  {
    defineProperty(target, prop, descriptor) {
      console.log(descriptor);
      return Reflect.defineProperty(target, prop, descriptor);
    },
  },
);

Object.defineProperty(p, "name", {
  value: "proxy",
  type: "custom",
}); // { value: 'proxy' }
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-proxy-object-internal-methods-and-internal-slots-defineownproperty-p-desc |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

另见
--

* `Proxy`
* `handler` (en-US)
* `Object.defineProperty()`
* `Reflect.defineProperty()`
handler.get()
=============

**`handler.get()`** 方法用于拦截对象的读取属性操作。

语法
--


```js
var p = new Proxy(target, {
  get: function (target, property, receiver) {},
});
```

### 参数

以下是传递给 get 方法的参数，`this 上下文绑定在`handler 对象上。

`target`

目标对象。

`property`

被获取的属性名。

`receiver`

Proxy 或者继承 Proxy 的对象

### 返回值

get 方法可以返回任何值。

描述
--

**`handler.get`** 方法用于拦截对象的读取属性操作。

### 拦截

该方法会拦截目标对象的以下操作：

* 访问属性：`proxy[foo] 和` `proxy.bar`
* 访问原型链上的属性：`Object.create(proxy)[foo]`
* `Reflect.get()`
### 约束

如果违背了以下的约束，proxy 会抛出 `TypeError`:

* 如果要访问的目标属性是不可写以及不可配置的，则返回的值必须与该目标属性的值相同。
* 如果要访问的目标属性没有配置访问方法，即 get 方法是 undefined 的，则返回值必须为 undefined。
示例
--

以下代码演示如何拦截属性值的读取操作。


```js
var p = new Proxy(
  {},
  {
    get: function (target, prop, receiver) {
      console.log("called: " + prop);
      return 10;
    },
  },
);

console.log(p.a); // "called: a"; ouptut 10
```


以下代码演示违反约束的情况。


```js
var obj = {};
Object.defineProperty(obj, "a", {
  configurable: false,
  enumerable: false,
  value: 10,
  writable: false,
});

var p = new Proxy(obj, {
  get: function (target, prop) {
    return 20;
  },
});

p.a; //会抛出 TypeError
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-proxy-object-internal-methods-and-internal-slots-get-p-receiver |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

另见
--

* `Proxy`
* `handler` (en-US)
* `Reflect.get()`
handler.has()
=============

**`handler.has()`** 方法是针对 `in` 操作符的代理方法。

尝试一下
----

语法
--


```js
var p = new Proxy(target, {
  has: function (target, prop) {},
});
```

### 参数

`下面是传递给 has` 方法的参数。`this` is bound to the handler.

`target`

目标对象。

`prop`

需要检查是否存在的属性。

### 返回值

`has` 方法返回一个 boolean 属性的值。

描述
--

**`handler.has`** 方法可以看作是针对 `in` 操作的钩子。

### 拦截

这个钩子可以拦截下面这些操作：

* 属性查询：`foo in proxy`
* 继承属性查询：`foo in Object.create(proxy)`
* `with` 检查`: with(proxy) { (foo); }`
* `Reflect.has()`
### 约束

如果违反了下面这些规则，proxy 将会抛出 `TypeError`:

* 如果目标对象的某一属性本身不可被配置，则该属性不能够被代理隐藏。
* 如果目标对象为不可扩展对象，则该对象的属性不能够被代理隐藏
示例
--

下面的代码拦截了 `in` 操作符。


```js
var p = new Proxy(
  {},
  {
    has: function (target, prop) {
      console.log("called: " + prop);
      return true;
    },
  },
);

console.log("a" in p); // "called: a"; outputs true
```


下面的代码违反了约束。


```js
var obj = { a: 10 };
Object.preventExtensions(obj);
var p = new Proxy(obj, {
  has: function (target, prop) {
    return false;
  },
});

"a" in p; // TypeError is thrown
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-proxy-object-internal-methods-and-internal-slots-hasproperty-p |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

其他
--

* `Proxy`
* `handler` (en-US)
* `in` operator
* `Reflect.has()`
handler.construct()
===================

**`handler.construct()`** 方法用于拦截 `new` 操作符。为了使 new 操作符在生成的 Proxy 对象上生效，用于初始化代理的目标对象自身必须具有 [[Construct]] 内部方法（即 `new target` 必须是有效的）。

尝试一下
----

语法
--


```js
var p = new Proxy(target, {
  construct: function (target, argumentsList, newTarget) {},
});
```

### 参数

下面的参数将会传递给 `construct` 方法，`this` 绑定在 handler 上。

`target`

目标对象。

`argumentsList`

constructor 的参数列表。

`newTarget`

最初被调用的构造函数，就上面的例子而言是 p。

### 返回值

`construct` 方法必须返回一个对象。

描述
--

**`handler.construct()`** 方法用于拦截 `new`操作符。

### 拦截

该拦截器可以拦截以下操作：

* `new proxy(...args)`
* `Reflect.construct()`
### 约束

如果违反以下约定，代理将会抛出错误 `TypeError`:

* 必须返回一个对象。
示例
--

下面代码演示如何拦截 `new` 操作。


```js
var p = new Proxy(function () {}, {
  construct: function (target, argumentsList, newTarget) {
    console.log("called: " + argumentsList.join(", "));
    return { value: argumentsList[0] \* 10 };
  },
});

console.log(new p(1).value); // "called: 1"; outputs 10
```


下面的代码违反了约定。


```js
var p = new Proxy(function () {}, {
  construct: function (target, argumentsList, newTarget) {
    return 1;
  },
});

new p(); // TypeError is thrown
```


下面的代码未能正确的初始化 Proxy。Proxy 初始化时，传给它的 `target` 必须具有一个有效的 constructor 供 `new` 操作符调用。


```js
var p = new Proxy(
  {},
  {
    construct: function (target, argumentsList, newTarget) {
      return {};
    },
  },
);

new p(); // TypeError is thrown, "p" is not a constructor
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

相关主题
----

* `Proxy`
* `handler` (en-US)
* `new` operator.
* `Reflect.construct()`
handler.setPrototypeOf()
========================

**`handler.setPrototypeOf()`** 方法主要用来拦截 `Object.setPrototypeOf()`.

语法
--


```js
var p = new Proxy(target, {
  setPrototypeOf: function (target, prototype) {},
});
```

### 参数

以下参数传递给 `setPrototypeOf` 方法。

`target`

被拦截目标对象。

`prototype`

对象新原型或为`null`.

### 返回值

如果成功修改了`[[Prototype]]`, `setPrototypeOf` 方法返回 `true`,否则返回 `false`.

描述
--

这个 **`handler.setPrototypeOf`** 方法用于拦截 `Object.setPrototypeOf()`.

### 拦截

这个方法可以拦截以下操作：

* `Object.setPrototypeOf()`
* `Reflect.setPrototypeOf()`
### Invariants

如果违反了下列规则，则 proxy 将抛出一个 `TypeError`：

* `如果 target` 不可扩展，原型参数必须与 `Object.getPrototypeOf(target)` 的值相同。
示例
--

如果你不想为你的对象设置一个新的原型，你的 handler 的 `setPrototypeOf` 方法可以返回 false，也可以抛出异常。

The former approach means that any operation that performs such mutation, that throws an exception on failure to mutate, will have to create the exception itself. For example, `Object.setPrototypeOf()` will create and throw a `TypeError` itself. If the mutation is performed by an operation that *doesn't* ordinarily throw in case of failure, such as `Reflect.setPrototypeOf()`, no exception will be thrown.


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

var newProto = {},
  target = {};

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


The latter approach will cause *any* operation that attempts to mutate, to throw. This approach is required if you want even non-throwing operations to throw on failure, or you want to throw a custom exception value.


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

var newProto = {},
  target = {};

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

Specifications
--------------

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

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `Proxy`
* `handler` (en-US)
* `Object.setPrototypeOf()`
* `Reflect.setPrototypeOf()`
handler.set()
=============

**`handler.set()`** 方法是设置属性值操作的捕获器。

尝试一下
----

语法
--


```js
new Proxy(target, {
  set(target, property, value, receiver) {
  }
});
```

### 参数

以下是传递给 `set()` 方法的参数。`this` 绑定在 handler 对象上。

`target`

目标对象。

`property`

将被设置的属性名或 `Symbol`。

`value`

新属性值。

`receiver`

最初接收赋值的对象。通常是 proxy 本身，但 handler 的 set 方法也有可能在原型链上，或以其他方式被间接地调用（因此不一定是 proxy 本身）。

**备注：** 假设有一段代码执行 `obj.name = "jen"`， `obj` 不是一个 proxy，且自身不含 `name` 属性，但是它的原型链上有一个 proxy，那么，那个 proxy 的 `set()` 处理器会被调用，而此时，`obj` 会作为 receiver 参数传进来。

### 返回值

`set()` 方法应当返回一个布尔值。

* 返回 `true` 代表属性设置成功。
* 在严格模式下，如果 `set()` 方法返回 `false`，那么会抛出一个 `TypeError` 异常。
描述
--

`handler.set()` 方法用于拦截设置属性值的操作。

### 拦截

该方法会拦截目标对象的以下操作：

* 指定属性值：`proxy[foo] = bar` 和 `proxy.foo = bar`
* 指定继承者的属性值：`Object.create(proxy)[foo] = bar`
* `Reflect.set()`
### 约束

如果违背以下的约束条件，proxy 会抛出一个 `TypeError` 异常：

* 若目标属性是一个不可写及不可配置的数据属性，则不能改变它的值。
* 如果目标属性没有配置存储方法，即 `[[Set]]` 属性的是 `undefined`，则不能设置它的值。
* 在严格模式下，如果 `set()` 方法返回 `false`，那么也会抛出一个 `TypeError` 异常。
示例
--

以下代码演示如何捕获属性的设置操作。


```js
var p = new Proxy(
  {},
  {
    set: function (target, prop, value, receiver) {
      target[prop] = value;
      console.log("property set: " + prop + " = " + value);
      return true;
    },
  },
);

console.log("a" in p); // false

p.a = 10; // "property set: a = 10"
console.log("a" in p); // true
console.log(p.a); // 10
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

另见
--

* `Proxy`
* `handler` (en-US)
* `Reflect.set()`