Skip to content
标签
note
字数
686 字
阅读时间
4 分钟

Reflect 对象与 Proxy 对象一样,也是 ES6 为了操作对象而提供的新 API

设计目的

(1) 将 Object 对象的一些明显属于语言内部的方法(比如 Object.defineProperty ),放到 Reflect 对象上

现阶段,某些方法同时在 ObjectReflect 对象上部署,未来的新方法将只部署在 Reflect 对象上。也就是说,从 Reflect 对象上可以拿到语言内部的方法。

(2) 修改某些 Object 方法的返回结果,让其变得更合理

(3) 让 Object 操作都变成函数行为

与 Proxy 对象的关联

Reflect 对象的方法与 Proxy 对象的方法一一对应,只要是 Proxy 对象的方法,就能在 Reflect 对象上找到对应的方法。这就让 Proxy 对象可以方便地调用对应的 Reflect 方法,完成默认行为,作为修改行为的基础。

特别点

get 中的 receiver 参数

Reflect.get(target, name, receiver) 方法查找并返回 target 对象的 name 属性,如果没有该属性,则返回 undefined

javascript
var myObject = {
  foo: 1,
  bar: 2,
  get baz() {
    return this.foo + this.bar;
  },
}

Reflect.get(myObject, 'foo') // 1
Reflect.get(myObject, 'bar') // 2
Reflect.get(myObject, 'baz') // 3

如果 name 属性部署了读取函数(getter),则读取函数的 this 绑定 receiver

javascript
var myObject = {
  foo: 1,
  bar: 2,
  get baz() {
    return this.foo + this.bar;
  },
};

var myReceiverObject = {
  foo: 4,
  bar: 4,
};

Reflect.get(myObject, 'baz', myReceiverObject) // 8

set 中的 receiver 参数

Reflect.set 方法设置 target 对象的 name 属性等于 value

javascript
var myObject = {
  foo: 1,
  set bar(value) {
    return this.foo = value;
  },
}

myObject.foo // 1

Reflect.set(myObject, 'foo', 2);
myObject.foo // 2

Reflect.set(myObject, 'bar', 3)
myObject.foo // 3

如果 name 属性设置了赋值函数,则赋值函数的 this 绑定 receiver

javascript
var myObject = {
  foo: 4,
  set bar(value) {
    return this.foo = value;
  },
};

var myReceiverObject = {
  foo: 0,
};

Reflect.set(myObject, 'bar', 1, myReceiverObject);
myObject.foo // 4
myReceiverObject.foo // 1

注意,如果 Proxy 对象和 Reflect 对象联合使用,前者拦截赋值操作,后者完成赋值的默认行为,而且传入了 receiver,那么 Reflect.set 会触发 Proxy.defineProperty 拦截。

javascript
let p = {
  a: 'a'
};

let handler = {
  set(target, key, value, receiver) {
    console.log('set');
    Reflect.set(target, key, value, receiver)
  },
  defineProperty(target, key, attribute) {
    console.log('defineProperty');
    Reflect.defineProperty(target, key, attribute);
  }
};

let obj = new Proxy(p, handler);
obj.a = 'A';
// set
// defineProperty

上面代码中,Proxy.set 拦截里面使用了 Reflect.set,而且传入了 receiver,导致触发 Proxy.defineProperty 拦截。这是因为 Proxy.setreceiver 参数总是指向当前的 Proxy 实例(即上例的 obj),而 Reflect.set 一旦传入 receiver,就会将属性赋值到 receiver 上面(即 obj),导致触发 defineProperty 拦截。如果 Reflect.set 没有传入 receiver,那么就不会触发 defineProperty 拦截

参考

Reflect - ECMAScript 6入门

贡献者

The avatar of contributor named as jiechen jiechen

页面历史

撰写