缘起
最近看好多童鞋私下问我这方面的问题,正好有点时间,小编写了篇文章科普下!
proxy与Reflect关系
相通点: api相通,经常混合使用
不同点:proxy可以看做是代理,中间件,Reflect是操作对象提供的api,可以看做是Object的升级版,增加兼容性,对浏览器和用户友好!
proxy中较难的点
proxy具体大家可以看文档,较难的点其实就是如何代理函数,下面大家花点时间认真阅读。
这里我们看2个API
- apply
- construct
apply是调用拦截,简单来说就是调用的时候拦截
示例1:
var target = function () { return 'target'; };
var handler = {
apply: function () {
return 'proxy';
}
};
var p = new Proxy(target, handler);
p() // "proxy"
示例2:
var handler = {
apply (target, ctx, args) {
console.log(args)
return Reflect.apply(...arguments);
}
};
var target = function () { return 'target'; };
var p = new Proxy(target, handler);
p(1, 2)
// [1, 2]
// 'target'
我们先来看示例1,p()调用,直接走了apply代理,返回’proxy’。
同样看示例二,p(1, 2)调用,直接走了apply代理,打印args,出现传入的[1, 2],Reflect.apply(…arguments)其实是Reflect.apply(target, ctx, args),又因为Reflect可以看作是Object/function,万物皆对象,所以Function.apply(target, ctx, args),也就是target.apply(ctx, args),所以就出现了’target’
示例3:
var handler = {
apply (target, ctx, args) {
return Reflect.apply(...arguments);
}
};
var target = function (a, b) { return a + b; };
var p = new Proxy(target, handler);
p(1, 2)
// 3
按照上面的逻辑,推断出来是3,是不是很简单
下面我们再来说说construct,这个是构造函数,也就是new的时候触发拦截
示例4:
const p = new Proxy(function () {}, {
construct: function(target, args) {
console.log('start: ' + args.join(', '));
return { v: args[0] * 100 };
}
});
(new p(1,2)),v
// start: 1,2
//100
这个很容易,传入1,2,construct拦截,打印出start: 1,2,args[0]是1,值自然是100
利用proxy实现个观察者模式
观察者模式说白了就是联动模式,一方改变,另外一方自然而然改变,看代码
const observers = new Set();
const observed = fn => observers.add(fn);
const observable = obj => new Proxy(obj, {
set: function(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver);
observers.forEach(observer => observer());
return result;
}
});
简单说下,new Set一个observers,然后往里面增加被监听的函数,不怕重复的话,数组也行,然后用proxy的set代理,只要触发set,就会同时触发observed 里面被监听的对象,就这么简单!
尾声
美好的时光总是短暂的,今天的分享就到这里了, 你学会了嘛!