100行代码让您学会JavaScript原生的Proxy设计模式

面向对象设计里的设计模式之Proxy(代理)模式,相信很多朋友已经很熟悉了。比如我之前写过代理模式在Java中实现的两篇文章:

Java代理设计模式(Proxy)的四种具体实现:静态代理和动态代理

Java动态代理之InvocationHandler最简单的入门教程

其实和Java一样,JavaScript从语言层面来讲,也提供了对代理这个设计模式的原生支持。我们用一个不到100行代码的例子来看看吧。

下面的代码创建了一个名叫Jerry的Employee对象,然后用函数hireEmployee雇用该Employee进行JavaScript开发:

function Employee(name){

     this.name = name;

};

Employee.prototype.work = function(language){

     console.log(this.name + " is developing with: " + language);

}

let jerry = new Employee("Jerry");

function hireEmployee(employee, language){

      employee.work(language);

}

hireEmployee(jerry, "JavaScript");

打印输出:

Jerry is developing with: JavaScript

现在Jerry在他的业余时间里想学习一些其他的编程语言,但是不想影响自己的本职工作。用技术语言来讲,就是希望Employee原型方法work执行时,打印一行额外的信息,但是不允许修改Employee函数和Employee.prototype.work本身。这时Proxy这种代理模式就派上用场了。

我们为work方法创建一个代理逻辑:

var proxyLogic = {
get: function(target, name) {
	if( name == "work"){
		var oriFun = target[name].bind(target);
		return function(language){
			oriFun(language);
			console.log("and also study other language in spare time");
		}
	}
}
}
;

重点看第二行的get方法。两个输入参数,target和name。Target代表当前执行方法的实例,即方法调用者。Name代表具体的方法名称。第4行我们把原始方法取出来,存放到变量oriFun里。第五行返回一个新的JavaScript函数,该函数体的实现逻辑为首先在第六行调用原始方法,然后在第七行执行额外的逻辑。

大家在回忆我之前介绍Java InvocationHandler实现动态代理的文章:

Java动态代理之InvocationHandler最简单的入门教程

是不是思路完全一样?都是在代理逻辑里调用原始方法,然后再执行额外的代码。

这个proxyLogic生成后,怎么把它同我们原始的需要被代理的代码关联起来呢?

只需要1行代码:

var jerryProxy = new Proxy(jerry, proxyLogic );

Proxy函数是JavaScript提供的原生代理构造器,需要两个输入参数:

第一个输入参数是我们的Employee实例,即需要被代码的对象实例,第二个输入参数是我们开发好的代理逻辑。返回的即是装配好的代理对象,该代理对象的work方法实现在第二个输入参数里。

现在我们再次调用hireEmployee,传入Proxy构造器返回的代理对象:

hireEmployee(jerryProxy, "JavaScript");

打印输出,代理逻辑生效了:

和Java的Invocation一样优雅地实现了代理设计模式。

使用Proxy代理设计模式的一个实际例子,请参考我的文章:

巧用代理设计模式(Proxy Design Pattern)改善前端图片加载体验

要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏自动化测试实战

flask第二十四篇——模板【6】自定义过滤器

2416
来自专栏Golang语言社区

go语言网络编程之tcp

go语言网络编程需要导入包 net如下 import ( "fmt" "net" ) 重要函数 func Listen(net, laddr s...

2486
来自专栏机器学习从入门到成神

2015百度校招笔试真题以及解析(二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_35512245/articl...

1842
来自专栏Vue ssr

Promise 源码分析

        3、外部一种实现promise的源码:https://github.com/ygm125/promise/blob/master/promise...

4255
来自专栏Coco的专栏

BAT及各大互联网公司2014前端笔试面试题--JavaScript篇

3065
来自专栏专注数据中心高性能网络技术研发

vim使用经验积累

vim用法: 1.搜索关键字 ---- 在常态下输入“/”,然后输入要搜索的关键字即可找到所有的关键字 2.在关键字之间跳转 ---- 搜索之后按n...

2694
来自专栏流浪猫的golang

go panic与recover分析及错误处理

error 是一种类型,表示错误状态的类型,如果没有错误则是nil。直白点将:error 类型就是描述错误的一种类型。

1103
来自专栏偏前端工程师的驿站

前端魔法堂——异常不仅仅是try/catch

前言  编程时我们往往拿到的是业务流程正确的业务说明文档或规范,但实际开发中却布满荆棘和例外情况,而这些例外中包含业务用例的例外,也包含技术上的例外。对于业务用...

2667
来自专栏飞雪无情的博客

Go语言 | Go 1.9 新特性 Type Alias详解

北京时间2017.08.25,Go1.9正式版发布了。Go1.9经历了2个beta,好几个月,终于定了,发布了正式版本。Go 1.9包含了很多改变,比如类型别名...

974
来自专栏程序员宝库

JavaScript 深拷贝性能分析

作者:justjavac 链接:https://segmentfault.com/a/1190000013107871 如何在 JavaScript 中拷贝一个...

42613

扫码关注云+社区