Reflect

  1. 从 Reflect 对象上可以获得语言内部的方法
  2. 修改某些 Object 方法的返回结果,让其变得更合理。比如 Object.defineProperty 在无法定义属性时会抛出一个错误,而 Reflect.defineProperty 则会返回 false
  3. 让 Object 操作都变成函数行为。
  4. 只要是 Proxy 对象的方法,就能在 Reflect 对象上找到相应的方法,无论 Proxy 怎么修改默认行为,总可以在 Reflect 上获取默认行为

静态方法

  • Reflect.apply(target, thisArg, args)
    等同于 Function.prototype.apply.call(func, thisArg, args),用于绑定 this 对象后执行给定函数。

  • Reflect.construct(target, args)
    等同于 new target(…args),提供了一种不使用 new 来调用构造函数的方法:

    1
    2
    3
    4
    5
    6
    7
    8
    function Greeting(name) {
    this.name = name
    }
    //new 的写法
    const instance = new Greeting("张三")

    //Reflect.construct 写法
    const instance = Reflect.construct(Greeting, ["张三"])
  • Reflect.get(target, name, receiver)
    查找并返回 target 的 name 属性,如果没有返回 undefined。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    let obj = {
    foo: 1,
    bar: 2,
    get baz() {
    return this.foo + this.bar
    },
    }
    Reflect.get(obj, "foo") //1
    Reflect.get(obj, "baz") //3
    如果 name 属性部署了 getter,则 getter 的 this 绑定 receiver:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    let obj = {
    foo: 1,
    bar: 2,
    get gaz() {
    return this.foo + this.bar
    },
    }
    let myobj = {
    foo: 2,
    bar: 4,
    }
    Reflect.get(obj, "gaz", myobj) //myobj.foo + myobj.bar 6
    如果第一个参数不是 object,会报错
    Reflect.set 会触发 Proxy.defineProperty 拦截:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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
  • Reflect.set(target, name, value, receiver)
    设置 target 的 name 属性等于 value。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    let obj = {
    foo: 1,
    set bar(value) {
    return (this.foo = value)
    },
    }
    obj.foo //1
    Reflect.set(obj, "foo", 2)
    obj.foo //2
    如果 name 属性设置了 setter,则 setter 的 this 绑定 receiver:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    let obj = {
    foo: 1,
    set bar(value) {
    return (this.foo = value)
    },
    }
    let myobj = {
    foo: 0,
    }
    Reflect.set(obj, "bar", 4, myobj)
    myobj.foo //4
    如果第一个参数不是 object,会报错
  • Reflect.defineProperty(target, name, descriptor)
    用来定义对象的属性。
  • Reflect.deleteProperty(target, name)
    等同于 delete obj[name],用于删除对象的属性,返回一个布尔值,删除成功返回 true,否则返回 false。
  • Reflect.has(target, name)
    对应 name in target 中的 in 运算符,如果第一个参数不是对象,Reflect.has 和 in 都会报错。
  • Reflect.ownKeys(target)
    返回对象的所有属性,包括 Symbol 属性。
  • Reflect.isExtensible(target)
    返回一个布尔值,表示当前对象是否可拓展。
  • Reflect.preventExtensions(target)
    用于使一个对象变为不可拓展的,返回一个布尔值,代表是否成功。
  • Reflect.getOwnPropertyDescriptor(target, name)
    基本等同于 Object.getOwnPropertyDescriptor(target, propertyKey),用于获得指定属性的描述对象。
  • Reflect.getPrototypeOf(target)
    用于读取对象的prop属性,对应 Object.getPrototypeOf(obj)。
  • Reflect.setPrototypeOf(target, prototype)
    用于设置对象的prop属性,返回第一个参数对象。

用 Proxy 实现观察者模式

Observe mode 指的是函数自动观察数据对象的模式,一旦对象有变化,函数就会自动执行。
思路:使用 observable 和 observe 这两个函数,observable 函数返回一个原始对象的 Proxy 代理,拦截赋值操作,触发充当观察者的各个函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const queueObservers = new Set()
const observe = (fn) => queueObservers.add(fn)
const observable = (obj) => new Proxy(obj, { set }) //拦截 set

function set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver) //完成原始操作
queueObservers.forEach((observer) => observer())
return result
}

const person = observable({
name: "张三",
age: 20,
})
function print() {
console.log(`${person.name}${person.age}`)
}

observe(print)
person.name = "李四" //李四,20