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 相关文章推荐
Jquery动态更改一张位图的src与Attr的使用
Jul 31 Javascript
jquery表单验证框架提供的身份证验证方法(示例代码)
Dec 27 Javascript
开源的javascript项目Kissy介绍
Nov 28 Javascript
使用CoffeeScrip优美方式编写javascript代码
Oct 28 Javascript
jquery validate demo 基础
Oct 29 Javascript
javascript中window.open在原来的窗口中打开新的窗口(不同名)
Nov 15 Javascript
基于jquery实现的银行卡号每隔4位自动插入空格的实现代码
Nov 22 Javascript
微信小程序-消息提示框实例
Nov 24 Javascript
关于laydate.js加载laydate.css路径错误问题解决
Dec 27 Javascript
关于axios不能使用Vue.use()浅析
Jan 12 Javascript
Vuex 在Vue 组件中获得Vuex 状态state的方法
Aug 27 Javascript
vue 解除鼠标的监听事件的方法
Nov 13 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
ThinkPHP模板判断输出Present标签用法详解
2014/06/30 PHP
javascript new后的constructor属性
2010/08/05 Javascript
js 实现在离开页面时提醒未保存的信息(减少用户重复操作)
2013/01/16 Javascript
为Javascript中的String对象添加去除左右空格的方法(示例代码)
2013/11/30 Javascript
如何书写高质量jQuery代码(使用jquery性能问题)
2014/06/30 Javascript
jquery获取radio值(单选组radio)
2014/10/16 Javascript
JS实现可直接显示网页代码运行效果的HTML代码预览功能实例
2015/08/06 Javascript
JavaScript编写简单的计算器
2015/11/25 Javascript
详解Bootstrap的aria-label和aria-labelledby应用
2016/01/04 Javascript
基于jQuery实现点击最后一行实现行自增效果的表格
2016/01/12 Javascript
Javascript实现图片加载从模糊到清晰显示的方法
2016/06/21 Javascript
常用原生js自定义函数总结
2016/11/20 Javascript
jQuery中animate的几种用法与注意事项
2016/12/12 Javascript
Bootstrap笔记—折叠实例代码
2017/03/13 Javascript
vue-cli初始化项目中使用less的方法
2018/08/09 Javascript
微信小程序图表插件wx-charts用法实例详解
2019/05/20 Javascript
layui 解决form表单点击无反应的问题
2019/10/25 Javascript
JS实现基本的网页计算器功能示例
2020/01/16 Javascript
antd vue table跨行合并单元格,并且自定义内容实例
2020/10/28 Javascript
让python的Cookie.py模块支持冒号做key的方法
2010/12/28 Python
python函数中return后的语句一定不会执行吗?
2017/07/06 Python
Python使用functools实现注解同步方法
2018/02/06 Python
python numpy 按行归一化的实例
2019/01/21 Python
python 计算数据偏差和峰度的方法
2019/06/29 Python
基于Python中的yield表达式介绍
2019/11/19 Python
pytorch中交叉熵损失(nn.CrossEntropyLoss())的计算过程详解
2020/01/02 Python
如何解决tensorflow恢复模型的特定值时出错
2020/02/06 Python
TensorFlow实现checkpoint文件转换为pb文件
2020/02/10 Python
pycharm下pyqt4安装及环境配置的教程
2020/04/24 Python
2021年的Python 时间轴和即将推出的功能详解
2020/07/27 Python
OpenCV利用python来实现图像的直方图均衡化
2020/10/21 Python
详解matplotlib绘图样式(style)初探
2021/02/03 Python
应届毕业生个人自荐信范文
2013/11/30 职场文书
《两个铁球同时着地》教学反思
2014/02/13 职场文书
初中学校对照检查材料
2014/08/19 职场文书
2014年保安个人工作总结
2014/11/13 职场文书