es6 代理(Reflect)和反射(Proxy)的學習總結

 =========================反射=======================
        Reflect: 反射

        1. Reflect是什麼:
         Reflect是一個內置的JS對象,它提供了一系列方法,可以讓開發者通過調用這些方法,訪問JS底層功能
        由於它類似於其他語言的反射,因此取名爲Reflect
        
        2. 它可以做什麼?
         使用Reflect可以實現屬性的取值,賦值,調用普通函數,調用構造函數,判斷屬性是否存在與對象中等

        3.這些功能存在,爲啥還有重複實現一次?
          ES5中提出一個概念: 減少魔法,讓代碼更加純粹

          這種理念很大程度上是受到了函數式編程的影響: plus(add(3)(2))(6)

          ES6進一步貫徹這種理念,它任務,對屬性內存的控制,原型鏈的修改,函數的調用等,
          這些都屬於底層實現,屬於一種魔法,因此,需要將他們提取出來,形成一個正常的API,
          並高度聚合到某個對象中,於是就造就了Reflect對像
        
        4. 它到底提供了哪些API呢?
           Reflect.set(target,propertyKey, value): 設置對象target的屬性propertyKey裏面的value,
            相當於對象.屬性 = 賦值;
            例如:
                 const obj = {
                        a: 1,
                    }

                    // 賦值
                    obj.a = 10;
                    // 等效於
                    Reflect.set(obj, 'a', 10)
          Reflect.get(target, key) : 讀取對象target對象的屬性propertyKey,等同於獲取對象的屬性值     
           例如:
             const obj = {
                a: 1,
            }

            // 賦值
            console.log(obj.a)
            // 等效於
            console.log(Reflect.get(obj, 'a'))

         Reflect.apply(target, thisArgument, argumentsList): 調用一個指定的函數,等效於綁定this和參數裂掉。等效於函數調用   
           例如:
               function methonds(a){
                    console.log("打印",a)
                }
                
                methonds(3);

                Reflect.apply(methonds, null, [3])

          Reflect.deleteProperty(obj, propertyKey): 刪除一個對象裏面的key和value, 相等於 delete      
          Reflect.defineProperty(target, propertyKey, attribute): 類似於Object.defineProperty, 
           不同的式如果配置出現問題,返回false而不是報錯
          Reflect.construct(target, arguementList) : 用構造函數創建一個對象
          Reflect.has(target, key): 判斷一個屬性是否包含某個對象,相當於 in  
     
     ======================代理===========================
     代理: 修改了底層實現的方式
     使用方法:
     // 代理一個目標對象
     new Proxy(target, handler)
     兩個參數:
     target: 目標對象
     handler: 是一個普通對象,其中可以重寫底層實現
     返回一個代理對象
     例如:
        const obj2 = {
            a: 1,
            b: 2
        }
        const proxy = new Proxy(obj, {
            set(target, propertyKey, value) {
               // target[propertyKey] = value;
                Reflect.set(target, propertyKey, value)
            },
            get(target, propertyKey){
                if(Reflect.has(target, propertyKey)){
                    retrun Reflect.get(target, propertyKey);
                }else{
                    retrun -1;
                }
            }
        })

      console.log(proxy)


		用代理和反射實現一些例子,常用的功能
		// 觀察者模式
        // 有一個對象,是觀察者,它用於觀察另外一個對象的屬性值變化,當屬性值變化後會受到通知,可能會做一些事情

        function observer(target) {
            render();
            const proxy = new Proxy(target, {
                set(target, propertyKey, value) {
                    Reflect.set(target, propertyKey, value);
                    render();
                },
                get(target, propertyKey) {
                    Reflect.get(target, propertyKey);
                }
            })

            function render() {
                let htmlStr = "";
                for (const item of Object.keys(target)) {
                    htmlStr += `<span>${item}:</span><span>${target[item]}</span></br>`
                }
                document.body.innerHTML = htmlStr;
            }
            return proxy;
        }

        const obj = {
            a: 1,
            b: 2,
        }
        const result = observer(obj);
        console.log(result);


        // 手寫一個給構造函數賦值的方法
        function proxyConstructor(className, ...agrs) {
            return new Proxy(className, {
                construct(className, agrsList) {
                    const constructObj = Reflect.construct(className, agrs);
                    for (const item in agrs) {
                        Reflect.set(constructObj, agrs[item], agrsList[item]);
                    }
                    return constructObj;
                }
            })
        }

        class User {

        }

        const userProxy = proxyConstructor(User, "name", "age", "sex");
        const user = new userProxy("twinkle", 18, '男');
        console.log(user)

        // 實現一個函數驗證器
        function proxyValication(funcName, ...agrs) {
            return new Proxy(funcName, {
                apply(funcName, thisArgument, argumentsList) {
                    // 驗證參數類型是否符合要求
                    argumentsList.forEach((item, index) => {
                        if (typeof item !== agrs[index]) {
                            throw new TypeError(`第${index + 1}參數${argumentsList[index]}不是${agrs[index]}類型`)
                        }
                    })
                    return Reflect.apply(funcName, thisArgument, argumentsList);
                }
            })
        }

        function sum(a, b) {
            return a + b;
        }
        const sumProxy = proxyValication(sum, "number", "number");
        const resultSum = sumProxy(1, 5898);
        console.log(resultSum);
		``



> ![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20200623194241732.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxNDk5Nzgy,size_16,color_FFFFFF,t_70)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章