zoukankan      html  css  js  c++  java
  • ES6 Proxy代理

    概述

    Proxy代理 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。它不直接操作对象,而是像代理模式。

    基本用法

    Proxy代理

    一个 Proxy 对象由两个部分组成: target 、 handler 。在通过 Proxy 构造函数生成实例对象时,需要提供这两个参数。 target 即目标对象, handler 是一个对象,声明了代理 target 的指定行为。

    let target = {   // target 可以为空对象,调用 set 方法,向目标对象中添加了 属性
        name: 'Tom',
        age: 24
    }
    let handler = {
        get: function(target, key) {
            console.log('getting '+key);
            return target[key]; // 不是target.key
        },
        set: function(target, key, value) {
            console.log('setting '+key);
            target[key] = value;
         return true; //严格模式下,set代理如果没有返回true,就会报错。 } } let proxy
    = new Proxy(target, handler) proxy.name // 实际执行 handler.get proxy.age = 25 // 实际执行 handler.set

    实例方法

    1、get(target, propKey, receiver) 用于拦截某个属性的读取(read)操作,就是在读取目标对象的属性之前,搞点事情。
    参数:
    target:目标对象
    property:属性名
    receiver:操作行为所针对的对象,一般指proxy实例本身
    let exam={};
    let proxy = new Proxy(exam, { get(target, propKey, receiver) { console.log('Getting ' + propKey); return target[propKey]; } })
    console.log(proxy.name);//undefined
    2、set(target, propKey, value, receiver) 用来拦截目标对象的赋值(write)操作
    参数:
    target:目标对象
    propertyName:属性名
    propertyValue:属性值
    receiver:Proxy实例本身
    let validator = {
        set: function(obj, prop, value) {
            if (prop === 'age') {
                if (!Number.isInteger(value)) {
                    throw new TypeError('The age is not an integer');
                    return false;    
                }
                if (value > 200) {
                    throw new RangeError('The age seems invalid');
                    return false;
                }
            }
            // 对于满足条件的 age 属性以及其他属性,直接保存
            obj[prop] = value;
            return true;
        }
    };
    let proxy= new Proxy({}, validator)
    proxy.age = 100;
    proxy.age           // 100
    proxy.age = 'oppps' // 报错
    proxy.age = 300     // 报错   

    3、apply(target, ctx, args)  用于拦截函数的调用、call 和 reply 操作。

      target 表示目标对象,

      ctx 表示目标对象上下文,

      args 表示目标对象的参数数组。

    function sub(a, b){
        return a - b;
    }
    let handler = {
        apply: function(target, ctx, args){
            console.log('handle apply');
            return Reflect.apply(...arguments);
        }
    }
    let proxy = new Proxy(sub, handler)
    proxy(2, 1) 
    // 1

    4、has(target,propkey)   拦截 propKey in proxy 的操作,返回一个布尔值。即在判断 target 对象是否存在 propKey 属性时,会被这个方法拦截。

    let proxy = new Proxy(exam, handler)
    'name' in proxy  

    5、deleteProperty(target, propKey) 拦截delete proxy[propKey]的操作,返回一个布尔值。用于拦截 delete 操作。如下是删除实例:

                var handler = {
                    deleteProperty(target,key){
                        console.log('key',key);
                        invariant(key,'delete');
                        delete target[key];
                        return true;
                    }
                };
                function invariant (key,action) {
                    if(key[0] === '_') {
                        throw new Error(`Invalid attempt to ${action} private "${key}" property`);
                        return false;
                    }
                }
                var target = {_prop:'foo',prop:'foo'};
                var proxy = new Proxy(target,handler);
                console.log("target1",target);//target1 {_prop: "foo", prop: "foo"}
                console.log("delete1",delete proxy.prop);//key prop   delete1 true
                console.log("target2",target);//target2 {_prop: "foo"}
                console.log("deletetarget",delete target._prop);//deletetarget true 直接删除
                console.log("target3",target);//target3 {}
                console.log("delete2",delete proxy._prop);//key _prop  Uncaught Error: Invalid attempt to delete private "_prop" property 通过代理则删除失败

    6、construct(target, args) 用于拦截 new 命令。返回值必须为对象。

    7、ownKeys(target) 用于拦截对象自身属性的读取操作。

    8、getPrototypeOf(target) 拦截对象原型操作

    9、isExtensible(target) 用于拦截 Object.isExtensible 操作。

    扩展:

    JavaScript中,对象的extensible属性用于表示是否允许在对象中动态添加新的property。ECMAScript 3标准中,所有的对象都是extensible的。ECMAScript 5标准中,所有的对象默认仍是extensible的,但可以通过设定来改变这一属性。查询一个对象是否是extensible的,可以使用Object.isExtensible()语句:

    ……

    学习原文   应用学习

  • 相关阅读:
    dev c++ 中显示计算机中丢失libiconv2.dll
    poj 1456 Supermarket
    codeforce 867E Buy Low Sell High
    Java编写程序时出现警告:Resource leak: input is never closed 解决方法
    codeforce 8A
    CF1110B
    ZOJ 1914 Arctic Network
    POJ 1258 Agri-Net
    Poj 1751 Highways
    ZOJ 2158 Truck History
  • 原文地址:https://www.cnblogs.com/liangtao999/p/11701224.html
Copyright © 2011-2022 走看看