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 setCapture 区域外事件捕捉
Mar 18 Javascript
如何将一个String和多个String值进行比较思路分析
Apr 22 Javascript
js中浮点型运算BUG的解决方法说明
Jan 06 Javascript
jQuery实现立体式数字动态增加(animate方法)
Dec 21 Javascript
详解Vue的computed(计算属性)使用实例之TodoList
Aug 07 Javascript
JS去掉字符串末尾的标点符号及删除最后一个字符的方法
Oct 24 Javascript
利用JS实现一个同Excel表现的智能填充算法
Aug 13 Javascript
jQuery中each遍历的三种方法实例分析
Sep 07 jQuery
微信小程序模板消息限制实现无限制主动推送的示例代码
Aug 27 Javascript
jquery实现的放大镜效果示例
Feb 24 jQuery
vue-cli3项目打包后自动化部署到服务器的方法
Sep 16 Javascript
uniapp微信小程序实现一个页面多个倒计时
Nov 01 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
利用curl 多线程 模拟 并发的详解
2013/06/14 PHP
php对csv文件的读取,写入,输出下载操作详解
2013/08/10 PHP
php实现的RSS生成类实例
2015/04/23 PHP
项目中应用Redis+Php的场景
2016/05/22 PHP
PHP使用FFmpeg获取视频播放总时长与码率等信息
2016/09/13 PHP
拖动table标题实现改变td的大小(css+js代码)
2013/04/16 Javascript
angular+webpack2实战例子
2017/05/23 Javascript
AngularJS中下拉框的基本用法示例
2017/10/11 Javascript
vue2.0项目实现路由跳转的方法详解
2018/06/21 Javascript
node.js到底要不要加分号浅析
2018/07/11 Javascript
轻量级富文本编辑器wangEditor结合vue使用方法示例
2018/10/10 Javascript
微信小程序学习笔记之跳转页面、传递参数获得数据操作图文详解
2019/03/28 Javascript
python多线程编程方式分析示例详解
2013/12/06 Python
详解Python中with语句的用法
2015/04/15 Python
Python中文分词实现方法(安装pymmseg)
2016/06/14 Python
Python基于pandas实现json格式转换成dataframe的方法
2018/06/22 Python
python tornado微信开发入门代码
2018/08/24 Python
opencv-python的RGB与BGR互转方式
2020/06/02 Python
python下对hsv颜色空间进行量化操作
2020/06/04 Python
浅谈如何使用python抓取网页中的动态数据实现
2020/08/17 Python
Feelunique德国官方网站:欧洲最大的在线美容零售商
2019/07/20 全球购物
英国性能汽车零件和发动机配件在线:Maxpeedingrods
2019/11/05 全球购物
XMLHttpRequest对象在IE和Firefox中创建方式有没有不同
2016/03/23 面试题
什么时候需要进行强制类型转换
2016/09/03 面试题
欢送退休感言
2014/02/08 职场文书
大学生个人求职口试自我评价
2014/02/16 职场文书
护士岗位职责
2014/02/16 职场文书
财务管理职业生涯规划书
2014/02/26 职场文书
《周恩来的四个昼夜》观后思想汇报范文两篇
2014/09/10 职场文书
单位介绍信格式
2015/01/31 职场文书
城南旧事电影观后感
2015/06/16 职场文书
新人入职感言
2015/07/31 职场文书
幼儿园教师暑期培训心得体会
2016/01/09 职场文书
《打电话》教学反思
2016/02/22 职场文书
nginx搭建图片服务器的过程详解(root和alias的区别)
2021/03/31 Servers
python基于opencv批量生成验证码的示例
2021/04/28 Python