总目录

从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. bzoj1070————2016——3——14

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1070: 题目概括: Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中 ...

  2. UVa 10706 - Number Sequence

    题目大意:Sk表示从1到k的字符序列,如S4为1234,现如今有如下的序列S1S2...Sk,形如1 12 123 1234这样的序列,给一个数n,让你去这个序列第n个位置上的数字. 可以构建出一个S ...

  3. mysql ++中文乱码问题

    使用mysql++读取mysql数据库,数据表中字符集为utf8,但是读取的时候中文字符串不能够正常显示.下面是测试程序: #include <iostream> #include < ...

  4. spring整合mybatis,springMVC的0配置文件方式

    0配置文件的形式主要是采用spring3.0提供的@configuration注解和spring容器在启动的时候会加载实现了WebApplicationInitializer的类,并调用其onStar ...

  5. 2.10. 代码片段:demo方法(Core Data 应用程序实践指南)

    该代码段我觉得没有太多东西 - (void)applicationDidBecomeActive:(UIApplication *)application { [self cdh]; [self de ...

  6. iframe截取网站部分内容实现思路及代码

    使用iframe可以截取网站的部分内容,主要配合width.height.overflow等属性来实现的,具体示例如下,需要的朋友不要错过. <div style="width:630 ...

  7. 如何用C语言封装 C++的类,在 C里面使用

    本文给出了一种方法.基本思想是,写一个 wrapper文件,把 C++类封装起来,对外只提供C语言的接口,和 C++i相关的都在  wrapper的实现文件里实现. 1. apple.h #ifnde ...

  8. 大型网站制作前端使用PHP后台逻辑用 Java

    对于网站团队,大概可以按照职责分为前端.后端.架构三种角色. 前端:负责所有和用户有交互的产品,包括 WEB以及手机客户端 后端:负责各种业务 API 的开发,以及服务器端其他系统的开发 架构:负责设 ...

  9. 这个发现是否会是RSA算法的BUG、或者可能存在的破解方式?

    笔者从事各种数据加解密算法相关的工作若干年,今天要说的是基于大数分解难题的RSA算法,可能有些啰嗦. 事情的起因是这样的,我最近针对一款芯片进行RSA CRT解密的性能优化.因为期望值是1024bit ...

  10. ProjectManager Beta 2 项目管理器发布

    上次载Alpha阶段有一个可用版本Alpha 8也在这个博客发布了,传送:http://www.cnblogs.com/deali/p/ProjectManager.html ProjectManag ...