资讯专栏INFORMATION COLUMN

ES6之Reflect

BingqiChen / 3220人阅读

摘要:查找并返回对象的属性例例属性部署了读取函数返回的是的参数对象注意如果的第一个参数不是对象,则会报错。它返回一个布尔值,表示是否操作成功用于返回对象的所有属性使用和实现观察者模式请参考观察者模式

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.ucloud.cn/yun/102865.html

相关文章

  • ES6Proxy & Reflection API

    摘要:的出现,使用内建对象的继承得以实现。属性不存在抛出异常是取值操作,而就是赋值操作,可以对属性值进行验证。属性必须为数字抛出异常接受两个参数被读取属性的原对象,即代理的目标。这个可以拦截内部方法,通过返回数组的值可以覆写其行为。 Proxy & Reflect extends的出现,使用内建对象的继承得以实现。Proxy可以拦截JS引擎内部目标的底层对象操作,这些底层操作被拦截后会触发响...

    yearsj 评论0 收藏0
  • 《深入理解ES6》笔记——代理(Proxy)和反射(Reflection)API(12)

    摘要:方法与代理处理程序的方法相同。使用给目标函数传入指定的参数。当然,不用反射也可以读取的值。的例子我们可以理解成是拦截了方法,然后传入参数,将返回值赋值给,这样我们就能在需要读取这个返回值的时候调用。这种代理模式和的代理有异曲同工之妙。 反射 Reflect 当你见到一个新的API,不明白的时候,就在浏览器打印出来看看它的样子。 showImg(https://segmentfault....

    ZHAO_ 评论0 收藏0
  • 《深入理解ES6》笔记——代理(Proxy)和反射(Reflection)API(12)

    摘要:方法与代理处理程序的方法相同。使用给目标函数传入指定的参数。当然,不用反射也可以读取的值。的例子我们可以理解成是拦截了方法,然后传入参数,将返回值赋值给,这样我们就能在需要读取这个返回值的时候调用。这种代理模式和的代理有异曲同工之妙。 反射 Reflect 当你见到一个新的API,不明白的时候,就在浏览器打印出来看看它的样子。 showImg(https://segmentfault....

    CatalpaFlat 评论0 收藏0
  • 《深入理解ES6》笔记——代理(Proxy)和反射(Reflection)API(12)

    摘要:方法与代理处理程序的方法相同。使用给目标函数传入指定的参数。当然,不用反射也可以读取的值。的例子我们可以理解成是拦截了方法,然后传入参数,将返回值赋值给,这样我们就能在需要读取这个返回值的时候调用。这种代理模式和的代理有异曲同工之妙。 反射 Reflect 当你见到一个新的API,不明白的时候,就在浏览器打印出来看看它的样子。 showImg(https://segmentfault....

    shiina 评论0 收藏0
  • 深入理解ES6《代理和反射》

    摘要:使用陷阱验证属性用于接收属性代理的目标的对象要写入的属性键被写入的属性的值操作发生的对象通常是代理属性必须是数字抛错用陷阱验证对象结构属性不存在抛出错误使用陷阱隐藏已有属性可以用操作符来检测给定对象中是否包含有某个属性,如果自有属性或原型属 使用set陷阱验证属性 let target = { name: target } let proxy = new Proxy(targe...

    Stardustsky 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<