JavaScript中AOP的实现与应用


Posted in Javascript onMay 06, 2019

1. 简介

AOP (Aspect Oriented Programming) ,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是函数式编程的一种衍生,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

JavaScript中AOP的实现与应用

2. 基础实现

使用过java spring的同学一定知道,其内分为三种通知,before(前置通知)、after(后置通知)、around(环绕通知)。
下面我们分别在js调用方法时实现这三种通知:

before(前置通知)

顾名思义,就是在函数调用前执行

Function.prototype.before = function (beforefun) {
 var _orgin = this; // 保存原函数引用
 return function () { // 返回包含了原函数和新函数的"代理函数"
 beforefun.apply(this, arguments); // 执行新函数,修正this
 return _orgin.apply(this, arguments); // 执行原函数
 }
};

var originFun = function(val){
 console.log('原型函数: '+val);
}

var newFun = originFun.before(function(){
 // 传入函数调用前处理方法
 console.log('before: ' + new Date().getTime())
})

newFun("测试前置通知");

// 调用结果
// before: 1557047939699
// 原型函数: 测试前置通知

after(后置通知)

与before正相反,在函数调用后执行

Function.prototype.after = function (afterfun) {
 var _orgin = this; // 保存原函数引用
 return function () { // 返回包含了原函数和新函数的"代理函数"
 var ret = _orgin.apply(this, arguments); // 执行原函数
 afterfun.apply(this, arguments); // 执行新函数,修正this
 return ret;
 }
};

var originFun = function(val){
 console.log('原型函数: '+val);
}

var newFun = originFun.after(function(){
 // 传入函数调用前处理方法
 console.log('after: ' + new Date().getTime())
})

newFun("测试后置通知");

// 调用结果
// 原型函数: 测试前置通知
// after: 1557047997647

around(环绕通知)

在方法执行前后分别执行

// 利用前面的before、after方法实现
Function.prototype.around = function(beforeFun, afterFun) {
	var _orgin = this;
	return function() {
		return _orgin.before(beforeFun).after(afterFun).apply(this, arguments);
	}
}

3. AOP遇到修饰器

JS在ES7的提案中终于增加了修饰器(Decorator)函数,它是用来修改类的行为,但是现在浏览器都不支持,需要使用Babel进行转换,当AOP与修饰器结合后,又会给我们带来什么呢?

日志记录

通过AOP与修饰器的结合会很方便的进行日志的记录或者函数执行时间的记录

class Person {
 @log
 say(nick) {
 return `hi ${nick}`;
 }
}

function log(target, name, decriptor){
 var _origin = descriptor.value;
 descriptor.value = function(){
 console.log(`Calling ${name} with `, argumants);
 return _origin.apply(null, arguments);
 };

 return descriptor;
}

var person = new Person();
person.say('小明');

判断用户登录状态

class User {
 @checkLogin
 getUserInfo() {
 console.log('获取用户信息')
 }
}

// 检查用户是否登录
function checkLogin(target, name, descriptor) {
 let method = descriptor.value
 descriptor.value = function (...args) {
 // 校验方法,假设这里可以获取到用户名/密码
 if (validate(args)) {
 method.apply(this, args)
 } else {
 console.log('没有登录,即将跳转到登录页面...')
 }
 }
}

let user = new User()
user.getUserInfo()

4. React中的AOP

在react中使用AOP思想的典型就是高阶组件(HOC),请看下面的例子

function HOCComp(WrappedComponent){
 return class HOC extends Component {
 render(){
 const newProps = {param: 'HOC'};
 return <div>
 <WrappedComponent {...this.props} {...newProps}/>
 </div>
 }
 }
}

@HOCComp
class OriginComponent extends Component {
 render(){
 return <div>这是原始组件{this.props.param}</div>
 }
}

上面例子中在HOCComp中定义新的props,并传入子组件中。我们也可以对OriginComponent组件中的一些props进行加工,或对OriginComponent外层进行再次包装。从而不必去修改内部组件,保持了功能上的解耦。

5. 总结

AOP思想在框架及项目中使用的很多,包括React高阶组件、日志记录、登录验证、redux中间件等。在开发中应该与OOP相辅相成,共同提高软件的健壮性及可维护性。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

参考资料

  • https://3water.com/article/160748.htm
  • https://3water.com/article/160753.htm
Javascript 相关文章推荐
javascript 无提示关闭窗口脚本
Aug 17 Javascript
验证javascript中Object和Function的关系的三段简单代码
Jun 27 Javascript
20款超赞的jQuery插件 Web开发人员必备
Feb 26 Javascript
基于mootools 1.3框架下的图片滑动效果代码
Apr 22 Javascript
jquery跟js初始化加载的多种方法及区别介绍
Apr 02 Javascript
jquery的ajax跨域请求原理和示例
May 08 Javascript
JavaScript中实现继承的三种方式和实例
Jan 29 Javascript
Java Mybatis框架入门基础教程
Sep 21 Javascript
详解WordPress开发中get_current_screen()函数的使用
Jan 11 Javascript
vue中添加mp3音频文件的方法
Mar 02 Javascript
vue element-ui table表格滚动加载方法
Mar 02 Javascript
详解vue中在循环中使用@mouseenter 和 @mouseleave事件闪烁问题解决方法
Apr 07 Javascript
使用 vue 实现灭霸打响指英雄消失的效果附demo
May 06 #Javascript
vue如何截取字符串
May 06 #Javascript
用vscode开发vue应用的方法步骤
May 06 #Javascript
微信小程序合法域名配置方法
May 06 #Javascript
手把手教你使用TypeScript开发Node.js应用
May 06 #Javascript
微信小程序上线发布流程图文详解
May 06 #Javascript
ES6的解构赋值实例详解
May 06 #Javascript
You might like
菜鸟修复电子管记
2021/03/02 无线电
php 删除cookie方法详解
2014/12/01 PHP
PHP实现的购物车类实例
2015/06/17 PHP
PHP读取XML格式文件的方法总结
2017/02/27 PHP
js可突破windows弹退效果代码
2008/08/09 Javascript
brook javascript框架介绍
2011/10/10 Javascript
基于KMP算法JavaScript的实现方法分析
2013/05/03 Javascript
file控件选择上传文件确定后触发的js事件是哪个
2014/03/17 Javascript
教你如何使用PHP输出中文JSON字符串
2014/05/22 Javascript
node.js中的path.join方法使用说明
2014/12/08 Javascript
js实现将选中值累加到文本框的方法
2015/08/12 Javascript
基于jQuery实现放大镜特效
2020/10/19 Javascript
JS获取元素多层嵌套思路详解
2016/05/16 Javascript
jQuery Easyui使用(二)之可折叠面板动态加载无效果的解决方法
2016/08/17 Javascript
js实现带缓动动画的导航栏效果
2017/01/16 Javascript
解决ajax不能访问本地文件问题(利用js跨域原理)
2017/01/24 Javascript
SVG描边动画
2017/02/23 Javascript
Node.js 8 中的重要新特性
2017/06/28 Javascript
Express+Nodejs 下的登录拦截实现代码
2017/07/01 NodeJs
Vue-Router进阶之滚动行为详解
2017/09/13 Javascript
Angular搜索 过滤 批量删除 添加 表单验证功能集锦(实例代码)
2017/10/25 Javascript
Angular实现表单验证功能
2017/11/13 Javascript
vue使用i18n实现国际化的方法详解
2019/09/05 Javascript
解决vue-cli@3.xx安装不成功的问题及搭建ts-vue项目
2020/02/09 Javascript
Python3写入文件常用方法实例分析
2015/05/22 Python
python实现批量修改图片格式和尺寸
2018/06/07 Python
PyQt5响应回车事件的方法
2019/06/25 Python
python 中xpath爬虫实例详解
2019/08/26 Python
python轮询机制控制led实例
2020/05/03 Python
Html5页面二次分享的实现
2018/07/30 HTML / CSS
澳大利亚领先的美容护肤品零售商之一:SkincareStore
2018/01/22 全球购物
创建学习型党组织实施方案
2014/03/29 职场文书
幼儿园健康教育方案
2014/06/14 职场文书
一年级数学下册复习计划
2015/01/17 职场文书
保安辞职信范文
2015/02/28 职场文书
公司停电通知
2015/04/15 职场文书