zoukankan      html  css  js  c++  java
  • 从C#到TypeScript

    总目录

    从C#到TypeScript - Proxy

    我们知道在C#中要实现代理功能需要自己来实现代理类,并且每个类需要不同的代理类,使用起来不方便,虽然借助一些AOP框架可以一定程度实现拦截,但毕竟框架级别的还是太重了。
    现在ES6倒是出了个解决方案,Proxy是ES6推出的用于拦截操作的一层代理实现,TypeScript当然也同样支持,下面来看下Proxy是怎么用的。

    Proxy使用

    Proxy本身是一个类,可以通过new来实例化一个代理。

    let p = new Proxy(target, handle)
    

    Proxy有两个参数:
    target指所要代理的对象。
    handle也是一个对象,对象里包含对target操作的拦截。
    看个例子:

    let obj = { name: 'brook' };
    let p = new Proxy(obj, {
        get(target, property){
            return 'cnblogs';
        }
    });
    
    console.info(obj.name); // brook
    console.info(p.name); // cnblogs
    

    可以看到,p做为obj的代理,在handle里加了对目标对象的属性get操作进行拦截,所以第一次直接输出obj的name是'brook',用代理p输出就变成'cnblogs'了。
    因为handle里对获取属性操作进行了重新定义。
    get函数同样有两个参数,target仍然是操作对象,另一个property则是要访问的属性的名字。

    Proxy可拦截的操作

    • get(target, propKey, receiver)

    • set(target, propKey, value, receiver)

    • apply(target, object, args)

    • defineProperty(target, propKey, propDesc)

    • deleteProperty(target, propKey)

    • has(target, propKey)

    • ownKeys(target)

    • construct(target, args)

    • getPrototypeOf(target)

    • setPrototypeOf(target, proto)

    • getOwnPropertyDescriptor(target, propKey)

    • isExtensible(target)

    • preventExtensions(target)

    看过上一篇Reflect的有没有很熟,没错,Reflect里的操作Proxy里都同样有一份,这样在做Proxy的时候,如果要回到原始的结果,直接调用Reflect对应的操作就好。
    接下来挑几个重要的看看。

    get

    get(target, propKey, receiver)
    上面提到过get,不过没说第三个参数,其实receiver指的就是new出来的Proxy对象。

    let obj = { name: 'brook' };
    let p = new Proxy(obj, {
        get(target, property, receiver){
            console.info(receiver === p); // true
            return 'cnblogs'
        }
    });
    console.info(p.name);
    

    再来个例子来看看get能做到什么程度,我们知道数组的索引不能为负数,现在我们通过Proxy来让数组来支持它:

    let arr = ["b", "r", "o", "o", "k"];
    let p = new Proxy(arr, {
        get(target, property){
            let index = Math.abs(Number(property));  // 取负数的绝对值
            return arr[index];
        }
    });
    console.info(arr[2]);  // 输出o
    console.info(p[-2]);  //同样输出o
    

    set

    set(target, propKey, value, receiver)
    set用来拦截属性的赋值操作,比如number类型的数组,可以让它接受任何类型的值,当不是number的时候就给值0,当然这只是个不符合实际使用的功能演示:

    let arr = new Array<number>();
    let p = new Proxy(arr, {
        set(target, property, value, receiver){
            if(typeof value != 'number'){  // 不是number就设为0
                value = 0;
            }
    
            return Reflect.set(target, property, value);
        }
    });
    
    p[0] = 11;
    p[1] = "brook";
    
    console.info(arr[0]); // 11
    console.info(arr[1]); // 0
    

    现在前端MVVM很火,而用set就可以轻松做到设置属性值的同时更新Dom对象,实现绑定的效果。

    apply

    apply(target, object, args)
    这可以拦截函数的调用,第一个和第三个参数的意思很明确,分别指函数和函数的参数。
    第二个参数是指上下文的this,this的不同会可能导致函数里变量值的不同。

    class Test1{
        text: string = 'test1';
    
        func(){
            console.info('call test1 func')
            console.info(`I am brook in ${this.text}`);
        }
    }
    
    class Test2{
        text: string = 'test2';
    
        func(){
            console.info('call test2 func')
            console.info(`I am brook in ${this.text}`);
        }
    }
    
    let t1 = new Test1();
    let t2 = new Test2();
    
    let p = new Proxy(t1.func, {
        apply(target, thisArg, args){
            Reflect.apply(target, t2, args);
        }
    });
    
    p();
    
    

    上面代码输出信息如下:

    call test1 func
    I am brook in test2
    

    也就是实际调用的还是Test1的func,所以第一条输出为call test1 func,虽然Proxy代理的是Test1的func,但实际执行时传的this是t2,所以函数里的this指向了Test2,取的也就是test2中要实现代理功能需要自己来实现代理类,并且每个类需要不同的代理类,使用起来不方便,虽然借助一些AOP框架可以一定程度实现拦截,但毕竟框架级别的还是太重了。

    上面介绍了几个常用的,其他的意思也很明显就不多说了,Proxy的应用场景除了上面说过的MVVM外,还可以用在ORM中,把对象的行为映射到数据库中,还有数据访问的代理,总之想用到代理的可以考虑Proxy。
    还有就是要记住Proxy不是透明代理,它有自己的this,使用时需要注意。

  • 相关阅读:
    Python 安装Twisted 提示python version 2.7 required,which was not found in the registry
    Openfire Strophe开发中文乱码问题
    css div 垂直居中
    How to create custom methods for use in spring security expression language annotations
    How to check “hasRole” in Java Code with Spring Security?
    Android 显示/隐藏 应用图标
    Android 当媒体变更后,通知其他应用重新扫描
    文件上传那些事儿
    专题:点滴Javascript
    主流动画实现方式总结
  • 原文地址:https://www.cnblogs.com/brookshi/p/6426741.html
Copyright © 2011-2022 走看看