从C#到TypeScript - Proxy
总目录
从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的更多相关文章
- C# vs TypeScript - 高级类型
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - 变量
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - 接口
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - 类
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - function
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - 装饰器
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - Promise
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - Generator
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- 从C#到TypeScript - async await
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
随机推荐
- 1.3.1. 新建Xcode项目并设置故事板(Core Data 应用程序实践指南)
创建名为Grocery Dude的Single View程序,并按默认设置处理,不勾选Core Date 和 Git. 设计故事板: 选择Main.Storyboard 拖放一个 Table View ...
- 在asp.net中使用ajax记录
一.问题描述 ajax在mvc中使用频繁,比如cms中的评论功能,但由于涉及到前后端开发,日久容易忘,在此做下记录. 二.内容 控制器中代码示例: /// <summary> /// 在文 ...
- eclipse 标签标题乱码解决方法
一般出现此类问题都是由于更改本地语言设置引起的. 解决办法: 1.恢复到原来默认的语言和地域 2.更改eclipse主题(Window-->preferences-->General--& ...
- 3. 托管对象模型的迁移(Core Data 应用程序实践指南)
本章介绍如何添加模型版本及模型映射,演示几种迁移技术,供在升级模型时使用. 3.1. 修改托管对象模型 3.2. 添加模型版本 3.3. 轻量级迁移方式 3.4. 默认的迁移方式 3.5. 通过迁移管 ...
- --@angularJS--独立作用域scope绑定策略之=符策略
1.index.html: <!DOCTYPE HTML><html ng-app="app"><head> <title>s ...
- 响应的系统设置的事件——Configuration类简介
Configuration类专门用于描述手机设备上的配置信息,这些配置信息既包括用户特定的配置项,也包括系统的动态设置配置. 程序可调用Activity的如下方法来获取系统的Configuration ...
- Velocity教程
Velocity 语法(转) 一.基本语法 1."#"用来标识Velocity的脚本语句,包括#set.#if .#else.#end.#foreach.#end.#iinclud ...
- springMvc获取servletContext
springMvc获取servletContext WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebA ...
- 将SWF文件用作资源打包
使用Flash开发网页游戏少不了与各种美术资源打交道.对于静态资源的那就是各种图片,对于会动的资源可以考虑直接做成swf.制作成swf的美术资源又可以分为两种:一种是直接将关键帧罗列在主时间轴上,那么 ...
- Cocos2d-x 详解坐标系统
这篇博文将介绍一下在cocos2dx中的一些坐标系统概念: 一. (1) OpenGL坐标系 Cocos2D-x以OpenGL和OpenGL ES为基础,所以自然支持OpenGL坐标系.该坐标系原点在 ...