JavaScript实现AOP详解(面向切面编程,装饰者模式)


Posted in Javascript onDecember 19, 2017

什么是AOP?

AOP(面向切面编程)的主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来,这些跟业务逻辑无关的功能通常包括日志统计、安全控制、异常处理等。把这些功能抽离出来之后, 再通过“动态织入”的方式掺入业务逻辑模块中。

AOP能给我们带来什么好处?

AOP的好处首先是可以保持业务逻辑模块的纯净和高内聚性,其次是可以很方便地复用日志统计等功能模块。

JavaScript实现AOP的思路?

通常,在 JavaScript 中实现 AOP,都是指把一个函数“动态织入”到另外一个函数之中,具体的实现技术有很多,下面我用扩展 Function.prototype 来做到这一点。请看下面代码:

Function.prototype.before = function (beforefn) {
  var _self = this; //保存原函数引用
  return function () { //返回包含了原函数和新函数的"代理函数"
   beforefn.apply(this, arguments); //执行新函数,修正this
   return _self.apply(this, arguments); //执行原函数
  }
 };
 Function.prototype.after = function (afterfn) {
  var _self = this;
  return function () {
   var ret = _self.apply(this, arguments);
   afterfn.apply(this, arguments);
   return ret;
  }
 };
 var func = function () {
  console.log("2")
 }
 func = func.before(function () {
  console.log("1");
 }).after(function () {
  console.log("3");
 } )
 func();

执行结果如下:

JavaScript实现AOP详解(面向切面编程,装饰者模式)

我把负责打印数字1和打印数字3的两个函数通过AOP的方式动态植入func函数。通过执行上面的代码,我们看到控制台顺利地返回了执行结果1、2、3。

这种使用AOP的方式来给函数添加职责,也是JavaScript语言中的一种非常特别的巧妙的装饰者模式实现,下面我们来试试Function.prototype.before的威力,请看下面代码:

Function.prototype.before = function (beforefn) {
  var __self = this; // 保存原函数的引用
  return function () { // 返回包含了原函数和新函数的"代理"函数
   beforefn.apply(this, arguments); // 执行新函数,且保证 this 不被劫持,新函数接受的参数 // 也会被原封不动地传入原函数,新函数在原函数之前执行
   return __self.apply(this, arguments); // 执行原函数并返回原函数的执行结果, 2 // 并且保证 this 不被劫持
  }
 }
 Function.prototype.after = function (afterfn) {
  var __self = this;
  return function () {
   var ret = __self.apply(this, arguments);
   afterfn.apply(this, arguments);
   return ret;
  }
 };
 document.getElementById = document.getElementById.before(function(){ alert (1);
 });
 var button = document.getElementById( 'button' );

执行结果:

JavaScript实现AOP详解(面向切面编程,装饰者模式)

我们给document.getElementById()做了一些装饰,以后我们每次调用这个方法之前都会先执行alert("1")这条语句,但是请注意我们这条语句并不是写在了document.getElementById()这个方法的源码中,而只是在他的外部给他加了装饰,这样带来好处就是我们可以在不改变原方法的源码的情况下为他添加一些新的行为。国际惯例,举个栗子:

我的同事写了一个函数可以输出当前时间,而我现在的需求是输出当前天气之后再输出当前时间,下面有两种解决思路:

(1)传统解决办法: 拿同事的函数过来,找到他输出时间的代码,在这些代码之前加入输出当前天气的代码

(2)装饰者模式解决办法:拿同事的函数过来,不用看他的源码,直接给他的函数装饰一下,装饰的东西也就是输出当前天气的代码。

两种方法都解决了问题,但是他们的出发点是完全不同的:

(1)方法是改造原函数的内部,我们就需要去理解源代码,然后做修改。

(2)方法是给原函数添加了一层外套,我们根本不用管原本函数的内部实现。

现在又有了新的需求:在输出当前时间之前,先输出当前温度

(1)方法,我们在第一个需求已经把同事的代码改的面目全非了,现在又要重新理解函数内部,并加以修改(删除输出当前天气的代码,然后加入输出当前温度的代码)。

(2)方法,同事原本的函数是没有变的,我们现在给同事的函数换一件套(输出当前温度)就可以了。

以上这篇JavaScript实现AOP详解(面向切面编程,装饰者模式)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
firefox 和 ie 事件处理的细节,研究,再研究 书写同时兼容ie和ff的事件处理代码
Apr 12 Javascript
jQuery Selector选择器小结
May 06 Javascript
使用Jquery搭建最佳用户体验的登录页面之记住密码自动登录功能(含后台代码)
Jul 10 Javascript
基于jquery ui的alert,confirm方案(支持换肤)
Apr 03 Javascript
js上传图片及预览功能实例分析
Apr 24 Javascript
Node.js实现兼容IE789的文件上传进度条
Sep 02 Javascript
基于bootstrap-datetimepicker.js不支持IE8的快速解决方法
Nov 07 Javascript
Angular在一个页面中使用两个ng-app的方法(二)
Feb 20 Javascript
JavaScript中的遍历详解(多种遍历)
Apr 07 Javascript
vuejs实现本地数据的筛选分页功能思路详解
Nov 15 Javascript
Vue监听页面刷新和关闭功能
Jun 20 Javascript
JavaScript cookie原理及使用实例
May 08 Javascript
利用nginx + node在阿里云部署https的步骤详解
Dec 19 #Javascript
使用Vue自定义数字键盘组件(体验度极好)
Dec 19 #Javascript
vue 通过下拉框组件学习vue中的父子通讯
Dec 19 #Javascript
浅谈Vue.js中ref ($refs)用法举例总结
Dec 19 #Javascript
Vue 2.0学习笔记之使用$refs访问Vue中的DOM
Dec 19 #Javascript
jQuery实现弹窗下底部页面禁止滑动效果
Dec 19 #jQuery
基于node.js实现微信支付退款功能
Dec 19 #Javascript
You might like
德劲1102收音机的打理维修案例
2021/03/02 无线电
用php获取远程图片并把它保存到本地的代码
2008/04/07 PHP
MYSQL 小技巧 -- LAST_INSERT_ID
2009/11/24 PHP
jquery nth-child()选择器的简单应用
2010/07/10 Javascript
jQuery UI AutoComplete 自动完成使用小记
2010/08/21 Javascript
异步JavaScript编程中的Promise使用方法
2015/07/28 Javascript
js实现将选中值累加到文本框的方法
2015/08/12 Javascript
JS+CSS实现自动切换的网页滑动门菜单效果代码
2015/09/14 Javascript
jQuery遮罩层实例讲解
2017/05/11 jQuery
webpack实现热更新(实施同步刷新)
2017/07/28 Javascript
angularjs实现时间轴效果的示例代码
2017/11/29 Javascript
ES6之模版字符串的具体使用
2018/05/17 Javascript
微信小程序获取用户信息的两种方法wx.getUserInfo与open-data实例分析
2019/05/03 Javascript
jQuery列表动态增加和删除的实现方法
2020/11/05 jQuery
[01:06:30]DOTA2-DPC中国联赛定级赛 Phoenix vs DLG BO3第二场 1月9日
2021/03/11 DOTA
Python3基础之基本数据类型概述
2014/08/13 Python
使用Python制作获取网站目录的图形化程序
2015/05/04 Python
Python处理文本文件中控制字符的方法
2017/02/07 Python
Python基于聚类算法实现密度聚类(DBSCAN)计算【测试可用】
2018/12/26 Python
Django框架中序列化和反序列化的例子
2019/08/06 Python
Python实现某论坛自动签到功能
2019/08/20 Python
18个Python脚本可加速你的编码速度(提示和技巧)
2019/10/17 Python
wxPython+Matplotlib绘制折线图表
2019/11/19 Python
Python for循环与getitem的关系详解
2020/01/02 Python
Python Tricks 使用 pywinrm 远程控制 Windows 主机的方法
2020/07/21 Python
Python 读取位于包中的数据文件
2020/08/07 Python
Opencv python 图片生成视频的方法示例
2020/11/18 Python
西班牙最好的在线购买葡萄酒的商店:Vinoseleccion
2019/10/30 全球购物
请说出你所知道的线程同步的方法
2013/04/19 面试题
关于中国梦的演讲稿
2014/04/23 职场文书
乡镇安全生产月活动总结
2015/05/08 职场文书
2015年学生管理工作总结
2015/05/26 职场文书
校园开放日新闻稿
2015/07/17 职场文书
2019求职信:应届生求职信范文
2019/04/24 职场文书
java泛型通配符详解
2021/07/25 Java/Android
用python基于appium模块开发一个自动收取能量的小助手
2021/09/25 Python