欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ES6 Reflect初探

程序员文章站 2022-06-13 15:56:11
...

Reflect


基本概念

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

设计目的

  • 将object对象的一些属于语言内部的方法(比如Object.defineProperty),放到reflect对象上.也就是说在reflect对象上将拿到语言内部的方法
  • 修改某些object方法的返回结果,让其变得合理.比如, Object.defineProperty(obj, name, desc) 在无法定义属性时,会抛出一个错误,而 Reflect.defineProperty(obj, name, desc) 则会返回 false
  • 让object操作都变成函数行为.某些object操作是命令式,比如name in objdelete obj[name],而Reflect.has(obj,name)Reflect.deletePoroerty(obj,name)让它们变为函数行为
  • Reflect对象的方法和Proxy对象的方法一一对应,只要是proxy对象的方法,就能在reflect对象上找到相应的方法.这样proxy对象就可以方便的调用对应的reflect方法,完成默认行为.也就是说,无论proxy怎么修改默认行为,总可以在reflect上获取

静态方法

  1. Reflect.get(target,name,receiver)查找并返回target对象的name属性,没有的话返回undefined.如果第一个参数不是对象,方法报错

     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  baz的get重新定义了
    
     var myReceiverObject = {
     	foo: 4,
     	bar: 4,
     };
     Reflect.get(myObject, 'baz', myReceiverObject) // 8 这里指的是this指向了receiver
    
  2. Reflect.set(target,name,value,receiver):设置target对象的name属性等于value.如果第一个参数不是对象报错.用法和get一致.唯一注意的是:Reflect.set会触发Proxy.defineProperty拦截(Reflect.set在Proxy.set拦截中使用)

  3. Reflect.has(obj,name):对应name in obj中的in运算符.如果第一个参数不是对象,reflect.has和in运算符都会报错

  4. Reflect.deleteProperty(obj, name):等同于delete obj[name],用于删除对象的属性.返回一个布尔值,删除成功或要删除的属性不存在,返回true;删除失败,被删除的属性依然存在,返回false

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

     function Greeting(name) {
     	this.name = name;
     }
     // new 的写法
     const instance = new Greeting('张三');
     // Reflect.construct 的写法
     const instance = Reflect.construct(Greeting, ['张三']);
    
  6. Reflect.getPrototypeOf(obj):用于读取对象的__proto__属性,对应Object.getPrototypeOf(obj).唯一的区别是如果参数不是对象,Object.getPrototypeOf(obj)会将其转为对象,而Reflect.getPrototypeOf(obj)会报错

  7. Reflect.setPrototypeOf(obj, newProto):用于设置对象的__proto__属性,返回第一个参数对象,对应Object.setPrototypeOf(obj, newProto).
    (1) 如果第一个参数不是对象,Object.setPrototypeOf(obj, newProto)会返回第一个参数本身,而Reflect.setPrototypeOf(obj, newProto)会报错
    (2) 如果第一个参数是null或undefined,它们都会报错

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

  9. Reflect.defineProperty(target, propertyKey,attributes):基本等同于Object.defineProperty,用来为对象定义属性.推荐使用Reflect.defineProperty(target, propertyKey,attributes),因为另一个会被逐渐替代.如果Reflect.defineProperty第一个参数不是对象,就会抛出错误

  10. Reflect.getOwnPropertyDescriptor(target,propertyKey),基本等同于Object.getOwnPropertyDescriptor,用于得到指定属性的描述对象.唯一的区别是:如果第一个参数不是对象,Object.getOwnPropertyDescriptor不报错,返回undefined.而Reflect.getOwnPropertyDescriptor会抛出错误,表示参数非法

  11. Reflect.isExtensible (target):对应Object.isExtensible,返回一个布尔值,表示当前对象是否可以扩展.区别在于:如果参数不是对象,Object.isExtensible会返回false,因为非对象本来就是不可扩展的,而Reflect.isExtensible会报错

  12. Reflect.preventExtensions(target):对应Object.preventExtensions方法,用于让一个对象的变得不可扩展,返回一个布尔值,表示是否操作成功.区别是:如果参数不是对象,Object.preventExtensions 在 ES5 环境报错,在 ES6 环境返回传入的参数.而Reflect.preventExtensions 会报错

  13. Reflect.ownKeys (target):用于返回对象的所有属性,基本等同于Object.getOwnPropertyNames 与 Object.getOwnPropertySymbols 之和.即可以获取普通的键名,也可以获取Symbol值的键名