ES6学习笔记11 Reflect

Reflect对象设计目的

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

(2)修改某些Object方法的返回结果。例如Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)则会返回false。

(3)让Object操作都变成函数行为。例如原来的key in objdelete obj[key]Reflect.hasProperty(obj,key)Reflect.deleteProperty(obj,key)让其变为函数

(4)Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。

Proxy(target, {
  set: function(target, name, value, receiver) {
    var success = Reflect.set(target,name, value, receiver);
    if (success) {
      log('property ' + name + ' on ' + target + ' set to ' + value);
    }
    return success;
  }
});

上述代码拦截了对象的属性设置操作,但其在内部又调用了默认的属性复制行为

静态方法

Reflect对象的大部分方法与Object对象的同名方法作用是相同的,且与Proxy对象方法对应

  • Reflect.apply(target, thisArg, args)该方法等同于function.prototype.apply.call(func, thisArg, args)
function.prototype.apply.call(func, thisArg, args);
// 等同于
(FuncApply).call(func,thisArg,args);
// 等同于
func.FuncApply(thisArg,args);
// 等同于
func.applythisArgargs);
// 等同于
thisArgs.func(args);
// 为什么不直接写成func.applythisArgargs)呢,这是因为有可能函数本身定义了自己apply方法
  • Reflect.construct(target, args)该方法等同于new target(…args)
  • Reflect.get(target, name, receiver)查找并返回target对象的name属性,函数中this绑定receiver参数
//this 绑定receiver参数
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
  • Reflect.set(target, name, value, receiver)设置target对象的name属性值为value,函数中this绑定receiver参数,该方法的调用会触发Proxy.defineProperty拦截
  • Reflect.defineProperty(target, name, desc)等同于Object.defineProperty,如果第一个参数不是对象,会报错
  • Reflect.deleteProperty(target, name)等同于delete obj[name],用于删除对象属性,成功返回true
  • Reflect.has(target, name)对应于key in obj的in运算符,如果第一个参数不是对象,会报错
  • Reflect.ownKeys(target)返回对象自身所有属性,等同于Object.getOwnPropertyNames与Object.getOwnPropertySymbols之和
  • Reflect.isExtensible(target)对应于Object.isExtensible(target),如果第一个参数不是对象,会报错
  • Reflect.preventExtensions(target)对应于Object.preventExtensions(target),使对象不可扩展,如果参数不是对象,会报错
  • Reflect.getOwnPropertyDescriptor(target, name)等同于Object.getOwnPropertyDescriptor,如果第一个参数不是对象,会报错
  • Reflect.getPrototypeOf(target)读取对象的原型对象。其与Object.getPrototypeOf(target)区别在于,如果参数不是对象,后者会先转换为对象,而前者报错
  • Reflect.setPrototypeOf(target, prototype)设置对象的原型对象。如果第一个参数不是对象或为null、undefined,直接报错

实例使用Proxy实现观察者模式

const person = observable({
  name: '张三',
  age: 20
});

function print() {
  console.log(`${person.name}, ${person.age}`)
}

observe(print);
person.name = '李四';
// 输出
// 李四, 20
const queuedObservers = new Set();

const observe = fn => queuedObservers.add(fn);
const observable = obj => new Proxy(obj, {set});

function set(target, key, value, receiver) {
  const result = Reflect.set(target, key, value, receiver);
  queuedObservers.forEach(observer => observer());
  return result;
}

上述代码将所有观察者函数都放入集合中,然后拦截对象的属性赋值操作,一旦有属性改动,自动执行所有观察者函数

猜你喜欢

转载自blog.csdn.net/zjw_python/article/details/80957127
今日推荐