手机版

围绕Javascript aop(面向方面编程)的分析

时间:2021-09-09 来源:互联网 编辑:宝哥软件园 浏览:

Aop也叫面向方面编程,其中“通知”是方面的具体实现,可以分为前后左右。用过spring的同学一定很熟悉,但是在js中,AOP是一个被严重忽视的技术点。然而,使用aop可以有效地改进js代码逻辑。比如前端框架dojo和yui3中的AOP被提升为自定义事件的内部机制,在源代码中随处可见。由于这种抽象,dojo的定制事件非常强大和灵活。aop在dojo中的实现是在dojo/aspect模块中,主要有前、后、左右三种方法。本文将带领大家围绕方法一步步实现,后续文章将深入分析dojo/aspect模块的结构体系。

为了实现环绕通知,js应该想到的最简单的事情就是使用回调

advice=function(originalFunc){ console . log(' function之前');originalFunc();console.log('在函数之后');} var obj={ foo : function(){ console . log(' foo ');} }建议(obj.foo)结果:

前功能后功能哈哈,太简单了,能回去睡觉吗?

但是,是不是有点太粗暴了?我们同意包围它。至少对obj.foo的下一次调用应该是结果,而不是干巴巴的“foo”;出于这个原因,我-我们需要进行更改并使用闭包

advice=function(originalFunc){ return function(){ console . log('在function之前');originalFunc();console.log('在函数之后');} } var obj={ foo : function(){ console . log(this . name);},name : ' obj ' } obj . foo=advice(obj . foo)obj . foo()输出:

前功能后功能

包装的效果好像达到了,但是好名字在哪里呢?

我们必须处理建议返回的闭包中的范围问题

advice=function(originalFunc){ return function(){ console . log('在function之前');originalFunc();console.log('在函数之后');} } var obj={ foo : function(){ console . log(this . name);},name : ' obj ' } keepContext=function(){ return obj[' foo ']。呼叫(obj);} obj . foo=advice(keepContext);看来范围问题是用call解决的。让我们运行它,看看:

卧槽,这是传说中的无限循环吗?

看来我们还是要借助一个中间变量来改变和消除无限循环

advice=function(originalFunc){ return function(){ console . log('在function之前');originalFunc();console.log('在函数之后');} } var obj={ foo : function(){ console . log(this . name);},name : ' obj ' } var exist=obj . foo;keepContext=function(){ return exist . call(obj);} obj . foo=advice(keepContext);obj . foo();输出:

前函数后函数

哈哈,世界突然变好了。但是这一堆代码是不是显得太低了?我们想要一些高抽象吗?嗯,我也这么认为

函数围绕(obj,prop,advice){ var exist=obj[prop];var advised=advice(function(){ return exist . call(obj,arguments);});建议的。} advice=function(originalFunc){ return function(){ console . log('在function之前');originalFunc();console.log('在函数之后');} } var obj={ foo : function(){ console . log(this . name);},name: ' obj ' }左右(obj,' foo ',建议);obj . foo();方法将处理过程从具体对象中分离出来;建议只要按照以下格式写就能达到左右的效果

advice=function(originalFunc){ return function(){//在originalFunc()之前;//之后}}哈哈,我瞬间就长高了,对酷炫的日子很着迷。

那么问题来了:如果你不小心又一次调用了round方法,我该怎么办?呃。这是一个问题,我们是否应该像绑定/移除事件一样,让round返回一个带有移除方法的句柄来移除绑定。

移除就是让函数不执行相应的round方法,而只在下次执行时运行originalFunc方法

函数围绕{ var exist=obj[prop];var previous=function(){ return exist。调用(对象、参数);};var建议=建议(先前);建议的返回{ remove : function(){ obj[prop]=exist;建议=null previous=null exist=null obj=null } } } var计数=1;advice=function(originalFunc){ var current=count;返回函数(){控制台。log(' before function '当前);originalFunc(参数);控制台。log(' after function ' current);} } var obj={ foo : function(arg){ console。日志(这个。'姓名'和arg);},名称: 'obj'}h1=左右(obj,“foo”,建议);h2=左右(obj,“foo”,建议);物体。foo();h1。移除();物体。foo();H2。移除();物体。foo();输出:

函数2之前的函数一对象和函数一之后的[对象参数]函数2对象之后的函数一之前的函数1

这个。不但结果有点乱。还报错了。是可忍,叔不可忍,叔可忍,嫂不可忍!

啊,闭包。请赐予我力量吧!

函数围绕{ var exist=obj[prop];var previous=function(){ return exist。运用(物体、论据);};var建议=建议(先前);obj[prop]=function(){ //当调用移动后,建议为空//利用闭包的作用域链中可以访问到劝告跟以前的变量,根据劝告是否为空可以来决定调用谁建议退货?advised.apply(obj,arguments): previous。运用(物体、论据);};返回{ remove: function(){ //利用闭包的作用域链,在移动时将劝告置空,这样执行过程中不会进入本次大约/这几个不能删//obj[prop]=存在;建议=空建议=null//previous=null;//exist=null;//obj=null;} }}var计数=1;advice=function(originalFunc){ var current=count;返回函数(){控制台。log(' before function '当前);originalFunc.apply(这个,参数);控制台。log(' after function ' current);} } var obj={ foo : function(arg){ console。日志(这个。'姓名'和arg);},名称: 'obj'}h1=左右(obj,“foo”,建议);h2=左右(obj,“foo”,建议);物体。foo(' hello world ');h1。移除();物体。foo(' hello world ');H2。移除();物体。foo(' hello world ');

输出:

前功能2前功能1obj和你好世界后功能一后功能2前功能2 bj和你好世界后功能2 bj和你好世界打完,收功!

第一次通宵写博客也是醉了,两点钟听到隔壁去我的,四点钟听到乌鸦啼鸣,还有一种不知道什么鸟,啾啾的叫,五点钟这个时候一堆鸟叫。

参考文章:

使用面向切面编程改善爪哇岛描述语言代码

yui3的AOP(面向切面编程)和OOP(面向对象编程)

面向切面编程(AOP)的理解

版权声明:围绕Javascript aop(面向方面编程)的分析是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。