proxy与Reflect吃透

缘起


最近看好多童鞋私下问我这方面的问题,正好有点时间,小编写了篇文章科普下!

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 里面被监听的对象,就这么简单!

尾声


美好的时光总是短暂的,今天的分享就到这里了, 你学会了嘛!

猜你喜欢

转载自blog.csdn.net/zjscy666/article/details/119188578