ES6 Reflect


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标准入门第三版(阮一峰)>
发布了85 篇原创文章 · 获赞 16 · 访问量 6110

猜你喜欢

转载自blog.csdn.net/qq_43955202/article/details/104301427