ES6之Reflect

1、什么是Reflect?
操作对象而提供的新API


2、为什么要设计Reflect?
(1)将Object对象的属于语言内部的方法放到Reflect对象上,即从Reflect对象上拿Object对象内部方法。
(2)将用 老Object方法 报错的情况,改为返回false
老写法

try {
  Object.defineProperty(target, property, attributes);
  // success
} catch (e) {
  // failure
}

新写法

if (Reflect.defineProperty(target, property, attributes)) {
  // success
} else {
  // failure
}

(3)让Object操作变成函数行为
老写法(命令式写法)

'name' in Object //true

新写法

Reflect.has(Object,'name') //true

(4)Reflect与Proxy是相辅相成的,在Proxy上有的方法,在Reflect就一定有

    let target={}
    let handler={
      set(target,proName,proValue,receiver){
        //确认对象的属性赋值成功
        let isSuccess=Reflect.set(target,proName,proValue,receiver)
        if(isSuccess){
          console.log("成功")
        }
        return isSuccess
      }
    }
    let proxy=new Proxy(target,handler)

确保对象的属性能正确赋值,广义上讲,即确保对象的原生行为能够正常进行,这就是Reflect的作用


3、Reflect的API
注:由于和Proxy的API一致,所以参数就不解释了。

(1)Reflect.get(target,property,receiver)
查找并返回target对象的property属性
例1:

    let obj={
      name:"chen",
    }
    let result=Reflect.get(obj,"name")
    console.log(result) //chen 

例2:

    let obj={
      //属性yu部署了getter读取函数
      get yu(){
        //this返回的是Reflect.get的receiver参数对象
        return this.name+this.age
      }
    }

    let receiver={
      name:"shen",
      age:"18",
    }
    
    let result=Reflect.get(obj,"yu",receiver)
    console.log(result) //shen18

注意:如果Reflect.get()的第一个参数不是对象,则会报错。

(2)Reflect.set(target,propName,propValue,receiver)
设置target对象的propName属性为propValue
例1:

    let obj={
      name:"chen"
    }

    let result=Reflect.set(obj,"name","shi")
    console.log(result) //true
    console.log(obj.name) //shi

例2:原理同3(1)的例2

    let obj={
      age:38,
      set setAge(value){
        return this.age=value
      }
    }

    let receiver={
      age:28
    }

    let result=Reflect.set(obj,"setAge",18,receiver)
    console.log(result) //true
    console.log(obj.age) //38
    console.log(receiver.age) //18

(3)Reflect.set与Proxy.set联合使用,并且传入receiver,则会进行定义属性操作

    let obj={
      name:"chen"
    }

    let handler={
      set(target,key,value,receiver){
        console.log("Proxy拦截赋值操作")
        //Reflect完成赋值操作
        Reflect.set(target,key,value,receiver)
      },
      defineProperty(target,key,attribute){
        console.log("Proxy拦截定义属性操作")
        //Reflect完成定义属性操作
        Reflect.defineProperty(target,key,attribute)
      }
    }

    let proxy=new Proxy(obj,handler)
    proxy.name="ya"
    //Proxy拦截赋值操作
    //Proxy拦截定义属性操作
  • 为什么Reflect.set()传入receiver参数,就会触发定义属性的操作?
    因为Proxy.set()中的receiver是Proxy的实例(详情见这篇文章),即obj,而Reflect.set一旦传入receiver,就会将属性赋值到receiver上面,也是obj,所以就会触发defineProperty拦截。

(4)Reflect.has(obj,name)

var obj= {
  name: "chen",
};

老写法

'name' in obj // true

新写法

Reflect.has(obj, 'name') // true

(5)Reflect.deleteProperty(obj, name)
删除对象的属性

老写法:

delete obj.name;

新写法

Reflect.deleteProperty(obj, 'name');

(6)Reflect.construct(target, args)

function Person(name) {
  this.name = name;
}

new 的写法

let person= new Person('chen')

Reflect.construct 的写法

let person = Reflect.construct(Person, ['chen']);

(7)Reflect.getPrototypeOf(obj)
用于读取对象的proto属性,对应Object.getPrototypeOf(obj)

(8)Reflect.setPrototypeOf(obj, newProto)
设置目标对象的原型(prototype),对应Object.setPrototypeOf(obj, newProto)方法

(9)Reflect.apply(func, thisArg, args)
继承目标对象的特定方法

let array=[1,2,3,4,5,6]

老写法:

let small= Math.min.apply(Math, array) //1
let big = Math.max.apply(Math, array) //6
let type = Object.prototype.toString.call(small) //"[object Number]"

新写法:

const small= Reflect.apply(Math.min, Math, array)
const big = Reflect.apply(Math.max, Math, array)
//第三个参数是Object类型的就好,因为调用的是Object的原型方法toString
const type = Reflect.apply(Object.prototype.toString, small, [])

(10)Reflect.defineProperty(target, propertyKey, attributes)

function MyDate() {
  ...
  ...
}

老写法

Object.defineProperty(MyDate, 'now', {
  value: () => Date.now()
});

新写法

Reflect.defineProperty(MyDate, 'now', {
  value: () => Date.now()
});

与Proxy.defineProperty配合使用

let proxy = new Proxy({}, {
  defineProperty(target, prop, descriptor) {
    console.log(descriptor);
    return Reflect.defineProperty(target, prop, descriptor);
  }
});

proxy .name= 'chen';
// {value: "chen", writable: true, enumerable: true, configurable: true}
p.name // "chen"

如上,Proxy.defineProperty对属性赋值设置拦截,然后使用Reflect.defineProperty完成赋值

(11)Reflect.getOwnPropertyDescriptor(target, propertyKey)
基本等同于Object.getOwnPropertyDescriptor,用于得到指定属性的描述对象

(12)Reflect.isExtensible (target)
对应Object.isExtensible,返回一个布尔值,表示当前对象是否可扩展

(13)Reflect.preventExtensions(target)
对应Object.preventExtensions方法,用于让一个对象变为不可扩展。它返回一个布尔值,表示是否操作成功

(14)Reflect.ownKeys (target)
用于返回对象的所有属性


4、使用Proxy和Reflect实现观察者模式
请参考Javascript观察者模式

(完)



作者:小进进不将就
链接:https://www.jianshu.com/p/4a5eca0536c3
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值