1.reflect 概述
Reflect 对象与Proxy对象一样,也是ES6为了操作对象而提供的新的Api。Reflect对象的设计目的有以下几个。
-
1.1将Object对象上的一些明显属于语言内部的方法(类如Object.defineProperty)放到Reflect对象上。现阶段某些方法同时在Object和Recflect对象上部署,未来的新方法将旨在Reflect对象上部署。也就是说在Reflect对象上可以获得语言内部的方法。
-
1.2修改某些Object方法的返回结果,让其变得更加合理。比如,Object.defineProperty(obj.name,desc)在无法定义属性时会抛出一个错误,而Reflect。definedProperty(obj, name, desc)则会返回false。
旧写法
try{
Object.defineProperty(target, property, attributes);
//success
} catch(e){
//faliure
}
新写法
if(Reflect.defineProperty(target, property, attributes){
//seccess
}else{
//failure
}
- 1.3让Object操作都编程函数行为。某些Object操作是命令时,比如 name in obj和delete obj[name],而Reflect.has(obj, name)和Reflect。delete Property(obj, name)让他们变味了函数行为。
//旧写法
'assign' in Object //true
//新写法
Reflect.has(Object, 'assign') //true
- 1.4Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能放在Reflect对象上找到相应的方法。这就是Proxy对象可以方便的调用相应的Reflect方法来完成默认行为,作为修改行为的基础。也就是说,无论proxy怎么修改默认行为,我们总可以在Reflect上获取默认行为。
2.
Proxy(target,{
set(target, name, value, recevier){
let success = Reflect.set(target, name, value, recevier);
if(success){
console.log('property' + name + 'on' + target + 'set to' + value);
}
return success;
}
})
上面的代码中,Proxy方法拦截target对象的属性赋值行为。它采用Reflect.set方法将值赋给对象的属性,
确保完成原有的行为,然后再部署额外的功能。
3.再举一个例子
{
let obj = {name:'康家豪'}
let loggedObj = new Proxy(obj, {
get(target, name) {
console.log('get', target, name);
return Reflect.get(target, name);
},
deleteProperty(target, name) {
console.log('delete' + name);
return Reflect.defineProperty(target, name);
},
has(target, name){
console.log('has' + name);
return Reflect.has(target, name);
}
});
}
上面的代码中,每一个Proxy对象的拦截操作,内部都调用了相应的Reflect方法,保证了原生行为能够正常执行。
添加的工作就是将每一个操作输出一行日志。
2.Reflect的静态方法
- Reflect.apply(target, thisArg, args);
- Reflect.construct(target, args)
- Reflect.get(target, name, receiver)
- Reflect.set(target, name, value, receiver)
- Reflect.defineProperty(target, name, desc)
- Reflect.deleteProperty(target, name)
- Reflect.has(target, name)
- Reflect.ownKeys(target)
- Reflect.isExtensible(target)
- Reflect.preventExtensions(target)
- Reflect.getOwnPropertyDescriptor(target, name)
- Reflect.getPrototypeOf(target)
- Reflect.setPrototypeOf(target, prototype)
上面的这些方法的作用大部分与Object对象的同名方法的作用是想扽给的,而且与Proxy对象的方法是一一对应的。
3.实例方法
- 1.Reflect.get(target, name, receiver)
Reflect.get()方法用于查找并返回target对象的property属性
{
let obj = {
name: "kjh",
age:18,
get say(){
return this.name + this.age;
}
}
let result1 = Reflect.get(obj, "name");
let result2 = Reflect.get(obj, "age");
let result3 = Reflect.get(obj, "say")
console.log(result1) //kjh
console.log(result2) //18
console.log(result3) //kjh18
}
// //如果部署了读取函数(getter),则读取函数的this绑定recevier。
{
let obj = {
name:'kjh',
age:18,
get say(){
return this.name + this.age;
}
}
let myRecevierObj = {
name:'oiu',
age:99
}
console.log(Reflect.get(obj, 'say', myRecevierObj));
//oiu99
}
- 2.Reflect.set(target,property,value,receiver)
Reflect.set用于设置对象target的property属性为value
{
let obj = {
id:0,
set bar(value){
return this.id = value;
}
};
console.log(obj.id); //0
console.log(Reflect.set(obj,'id',9)); //true
console.log(obj.id); //9
}
{
let obj = {
id:0,
set bar(value){
return this.id = value;
}
};
let myRecevierObj = {
id:10
}
console.log(myRecevierObj.id); //10
console.log(Reflect.set(obj,'id',9,myRecevierObj)); //true
console.log(myRecevierObj.id); //9
}
{
let p = {
a:'a'
};
let handler = {
set(target, key, value, receiver){
console.log('set');
Reflect.set(target,key,value,receiver);
},
defineProperty(target,key,attributes){
console.log('defineProperty');
Reflect.defineProperty(target,key,attributes);
}
}
let obj = new Proxy(p,handler);
obj.a = 'A';
console.log(obj.a); //A
//set
//defineProperty
}
上面的代码中,proxy。set拦截使用了Reflect.set,导致触发了Proxy.definedProperty拦截。
- 3.Reflect.has(obj,property)
Reflect.has方法使用了对应name in Object 中的in运算符。
{
let obj = {
name:'kjh'
}
//旧写法
'name' in obj //true
//新写法
console.log(Reflect.has(obj,'name'));
//true
}
- 4.Reflect.deleteProperty(obj,property)
Reflect.deleteProperty(obj,property)用于删除对象的属性
{
let person = {
name:'kjh'
}
//旧写法
delete person.name; //true
//新写法
console.log(Reflect.deleteProperty(person,'name'));
//true
}
- 5.Reflect.construct(target,args)
Reflect.construct(target,args) 等同于new target(…args)提供了一种不适用new来调用构造函数的方法
{
function sayName(name){
this.name = name;
}
//new
let instance = new sayName('zs');
console.log(instance);
//sayName {name: "zs"}
//新方法
let instance2 = Reflect.construct(sayName,['ls']);
console.log(instance2);
// /sayName {name: "ls"}
//传入的第二个参数要是数组形式
}
-
6.Reflect.getPrototypeOf(obj)
用于读取对象的proto属性, 对应Object.getPrototypeOf(obj) -
7.Reflect.setPrototypeOf(obj, newProto)
设置目标对象的原型( prototype), 对应Object.setPrototypeOf(obj, newProto) 方法。 -
8.Reflect.apply(func, thisArg, args)
继承目标对象的特定方法
{
let args = [1,2,3,4,5,6];
//旧写法
let youngest = Math.min.apply(Math,ages);
let oldest = Math.max.apply(Math,args);
//新写法
let youngest = Reflect.apply(Math.min,Math,args);
let oldest = Reflect.apply(Math.max,Math,args);
}
- 9.Reflect.defineProperty(target, propertyKey, attributes)为对象定义属性。
{
let person = {
id:0
}
//旧写法
Object.defineProperty(person,'name',{
value:'小明'
})
//新写法
Reflect.defineProperty(person,'age',{
value:18
})
console.log(person);
// /{id: 0, name: "小明", age: 18}
}
- 10.Reflect.getOwnPropertyDescriptor(target, propertyKey) 获取对象指定属性的描述对象
{
let person = {
name:'kjh'
}
//旧写法
console.log(Object.getOwnPropertyDescriptor(person,'name'));
//{value: "kjh", writable: true, enumerable: true, configurable: true}
//新写法
console.log(Reflect.getOwnPropertyDescriptor(person,'name'));
//{value: "kjh", writable: true, enumerable: true, configurable: true}
}
(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观察者模式。
//使用Proxy实现观察者模式
{
function Person(name) {
this.name = name;
}
let son = new Person('灰太狼');
//proxy代理
let changeNameValue = new Proxy(son, {
set(target, property, value, receiver) {
if (property == 'name') {
console.log(`name 从 ${target[property]} 变为 ${value}`)
}
Reflect.set(target, property, value, receiver)
}
});
changeNameValue.name = '喜羊羊';
console.log(son);
// name 从 灰太狼 变为 喜羊羊
// Person {name: "喜羊羊"}
}
- 文档参考<ES6标准入门第三版(阮一峰)>