lixinliang

不懂用户体验的技术不是好设计

🎈 代理对象


简语

AOP,面向切面编程。

具体定义,网上资料很多,这里不再重复。

虽然,在构建一般项目下,

我们不一定常常围绕,AOP 模块来开发。

但是,在调试或者重构,我们会经常用到它。

举个栗子 🌰

https://github.com/lixinliang/use-vue/blob/c7dd7fad057c45bce0ea229fc9b6c223eea88a08/index.js#L70

这里,定义了一个变量,$mount 指向原函数。

并且,定义一个匿名函数,覆盖了原函数。

在匿名函数的内部,

我们可以添加我们需要的代码,

然后,通过 $mount.apply(this, arguments),无污染地重新实现原方法的逻辑。

AOP 就是这么个意思。

推荐一篇 AlloyTeam 的文章,有对 AOP 更深入的研究。

http://www.alloyteam.com/2013/08/yong-aop-gai-shan-javascript-dai-ma/

新特性

今天,讨论的内容,

主要是代理对象,也就是 ES6Proxy 对象。

Proxy 是一个构造函数,

但是,使用 Proxy 生成的实例对象,却不是 instanceof Proxy

例如,我换成了 Promise 对象。

关于

Proxy 对象用于截获对另一个对象执行的内部低级别操作。

代理对象可以用于拦截、对象虚拟化、日志记录/分析和其他用途。 ⛳️

怎么个意思呢?

响应式

简单来说,

我们都知道,当代的三大主流的数据驱动框架(MVVM)ReactAngularVue

在高级浏览器中,为了实现响应式数据,

它们的底层实现,都离不开 gettersetter

举个栗子 🌰

我们定义了,window 对象的 test 属性的 gettersetter

因此,当我们访问 test 的时候,包括使用它赋值、计算、传参等,

都进入了 getter 的钩子函数,

在返回内容时,我们可以处理一些逻辑。

setter 道理同上。

代理

gettersetter 带给了我们非常多的便利,

不过,前提是,我们知道,这个属性的名字叫 test

因此,代理对象就诞生了。

代理对象,可以理解为,

整个对象的,任意属性,都应用了 gettersetter

举个栗子 🌰

无论我们访问 ab 还是 c,都进入了 getter 的钩子函数,

我们根本不需要担心,用户想访问什么,

一切都在目标射程之内 🎯

我们既可以根据不同的情况返回不同的内容,

当然也可以返回相同内容,

或者作为 fallback 的默认值。

黑科技

而且,

为什么,我们就不能返回 Proxy 我自己呢?

这样,我们就永远跟 undefined 讲再见了。 👋

代码如下:

var anything = new Proxy({}, {
    get () {
        console.log('getter');
        return anything;
    },
    set () {
        console.log('setter');
        return anything;
    },
});

新玩具

访问是没有问题了,

不过,调用方法还是会报错。

所以,我们传入的参数,从 {} 改为 function () {}

就可以了。

具体实现如下:

https://github.com/lixinliang/proxy-any

https://www.npmjs.com/package/proxy-any

我们的新玩具,就诞生了:

场景

在开发某些工作项目的时候,

开发环境生产环境,并不是完全一致,

取决于,运行我们的代码的宿主,可能是 ChromeWechatAppElectron 甚至 Node 等等。

宿主提供的 API 我们在 开发环境 并不具备,

这时候,ProxyAny 主要目的是简单实现这些 API

我们并不需要完全实现等同的效果,

handle 的回调函数里面,我们只需要确保代码不报错,让程序继续执行而已。

灵感