总目录

从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,使用时需要注意。

从C#到TypeScript - Proxy的更多相关文章

  1. C# vs TypeScript - 高级类型

    总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...

  2. 从C#到TypeScript - 变量

    总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...

  3. 从C#到TypeScript - 接口

    总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...

  4. 从C#到TypeScript - 类

    总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...

  5. 从C#到TypeScript - function

    总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...

  6. 从C#到TypeScript - 装饰器

    总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...

  7. 从C#到TypeScript - Promise

    总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...

  8. 从C#到TypeScript - Generator

    总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...

  9. 从C#到TypeScript - async await

    总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...

随机推荐

  1. JavaWeb:EL & JSTL

    EL:全名为 Expression Language 1.语法:${sessionScope.user.sex}(从Session 的范围中,取得用户的性别), 所有的EL 都是以 ${  为起始,以 ...

  2. Intellij idea 15配置tomcat,maven

    刚导了个项目进去,想把项目运行起开,怎么也找不到tomcat... ctrl + alt +s,打开设置窗,搜索 Application Server Tomcat: 点中间绿色的“+”号,添加选择t ...

  3. 兼容ie6及以上的阴影滤镜的写法

    .subnav{ width: 220px; _width:160px; min-height: 168px; border: 1px solid #d0d8da; background: #fff; ...

  4. Hibernate常见异常

    1.数据库编码问题 主要错误信息 WARN: SQL Error: 1366, SQLState: 22001 ... ERROR: Data truncation: Incorrect string ...

  5. delphi中获得进程列表或想要的进程(枚举进程、遍历进程)

    一个常见的编程任务是枚举所有运行的"应用程序".Windows 任务管理器就是一个很好的例子.它用两种方式列出"应用程序".任务管理器的第一个选项卡列出桌面上的 ...

  6. Servlet 异步处理

    web容器会为每个请求分配一个线程,Servlet3.0新增了异步处理,解决多个线程不释放占据内存的问题.可以先释放容器分配给请求的线程与相关资源,减轻系统负担,原先释放了容器所分配线程的请求,其响应 ...

  7. 谱聚类 Spectral Clustering

    转自:http://www.cnblogs.com/wentingtu/archive/2011/12/22/2297426.html 如果说 K-means 和 GMM 这些聚类的方法是古代流行的算 ...

  8. Java线程:什么是线程

    一 基本概念 多任务:同一时刻运行多个程序的能力.每一个任务称为一个线程.可以同时运行一个以上线程的程序称为多线程程序. Java编写程序都运行在在Java虚拟机(JVM)中,在JVM的内部,程序的多 ...

  9. STL内存管理

    1. 概述 STL Allocator是STL的内存管理器,也是最低调的部分之一,你可能使用了3年stl,但却不知其为何物. STL标准如下介绍Allocator the STL includes s ...

  10. spring mvc redirect设置FlashAttribute

    在Controller中设置: @RequestMapping("/redir") public String redir(Model model, RedirectAttribu ...