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 相关文章推荐
js报错 Object doesn't support this property or method的原因分析
Mar 31 Javascript
js中 关于undefined和null的区别介绍
Apr 16 Javascript
JavaScript中匿名、命名函数的性能测试
Sep 04 Javascript
js网页右下角提示框实例
Oct 14 Javascript
深入探讨JavaScript String对象
Mar 09 Javascript
javascript实现验证身份证号的有效性并提示
Apr 30 Javascript
JS组件Bootstrap Select2使用方法解析
May 30 Javascript
JavaScript之WebSocket技术详解
Nov 18 Javascript
vue引入swiper插件的使用实例
Jul 19 Javascript
详解vue+webpack+express中间件接口使用
Jul 17 Javascript
jquery获取元素到屏幕四周可视距离的方法
Sep 05 jQuery
Javascript实现简易天数计算器
May 18 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
PHP设计聊天室步步通
2006/10/09 PHP
php中time()和mktime()方法的区别
2013/09/28 PHP
php file_get_contents抓取Gzip网页乱码的三种解决方法
2013/11/12 PHP
destoon常用的安全设置概述
2014/06/21 PHP
LINUX下PHP程序实现WORD文件转化为PDF文件的方法
2016/05/13 PHP
php使用fputcsv实现大数据的导出操作详解
2020/02/27 PHP
JavaScript中this关键字使用方法详解
2007/03/08 Javascript
js Html结构转字符串形式显示代码
2011/11/15 Javascript
JavaScript语言核心数据类型和变量使用介绍
2013/08/23 Javascript
jquery选择器、属性设置用法经验总结
2013/09/08 Javascript
js判断IE浏览器版本过低示例代码
2013/11/22 Javascript
javascript实现简单的Map示例介绍
2013/12/23 Javascript
JavaScript获取数组最小值和最大值的方法
2015/06/09 Javascript
JavaScript中判断两个字符串是否相等的方法
2015/07/07 Javascript
javascript和jquery实现用户登录验证
2016/05/04 Javascript
javascript实现秒表计时器的制作方法
2017/02/16 Javascript
JS常用正则表达式总结【经典】
2017/05/12 Javascript
ReactNative页面跳转Navigator实现的示例代码
2017/08/02 Javascript
vue 虚拟dom的patch源码分析
2018/03/01 Javascript
JS实现烟花爆炸效果
2020/03/10 Javascript
vue+iview使用树形控件的具体使用
2020/11/02 Javascript
如何在vue 中使用柱状图 并自修改配置
2021/01/21 Vue.js
Python3.4实现从HTTP代理网站批量获取代理并筛选的方法示例
2017/09/26 Python
python爬虫使用cookie登录详解
2017/12/27 Python
Python求出0~100以内的所有素数
2018/01/23 Python
结合OpenCV与TensorFlow进行人脸识别的实现
2019/10/10 Python
Python中的延迟绑定原理详解
2019/10/11 Python
python mock测试的示例
2020/10/19 Python
python实现不同数据库间数据同步功能
2021/02/25 Python
英国时尚运动品牌的合集:The Sports Edit
2017/12/20 全球购物
酒吧员工的岗位职责
2013/11/26 职场文书
安全标准化实施方案
2014/02/20 职场文书
求职信模板
2014/05/23 职场文书
高一学年自我鉴定范文(3篇)
2014/09/26 职场文书
体育运动会广播稿
2014/10/05 职场文书
「偶像大师 MILLION LIVE!」七尾百合子手办开订
2022/03/21 日漫