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 相关文章推荐
用js重建星际争霸
Dec 22 Javascript
Prototype使用指南之form.js
Jan 10 Javascript
Javascript 实现的数独解题算法网页实例
Oct 15 Javascript
js模拟hashtable的简单实例
Mar 06 Javascript
HTML页面登录时的JS验证方法
May 28 Javascript
javascript中attribute和property的区别详解
Jun 05 Javascript
流量统计器如何鉴别C#:WebBrowser中伪造referer
Jan 07 Javascript
jquery实现LED广告牌旋转系统图片切换效果代码分享
Aug 26 Javascript
jquery实现隐藏在左侧的弹性弹出菜单效果
Sep 18 Javascript
js生成随机颜色方法代码分享(三种)
Dec 29 Javascript
微信小程序滑动选择器的实现代码
Aug 10 Javascript
小程序实现上传视频功能
Aug 18 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
PHP无敌近乎加密方式!
2010/07/17 PHP
通过curl模拟post和get方式提交的表单类
2014/04/23 PHP
Yii2分页的使用及其扩展方法详解
2016/05/23 PHP
php版微信js-sdk支付接口类用法示例
2016/10/12 PHP
PHP容器类的两种实现方式示例
2019/07/24 PHP
thinkPHP5使用Rabc实现权限管理
2019/08/28 PHP
javascript中的undefined 与 null 的区别  补充篇
2010/03/17 Javascript
js函数在frame中的相互调用详解
2014/03/03 Javascript
基于JavaScript将表单序列化类型的数据转化成对象的处理(允许对象中包含对象)
2015/12/28 Javascript
使用struts2+Ajax+jquery验证用户名是否已被注册
2016/03/22 Javascript
canvas快速绘制圆形、三角形、矩形、多边形方法介绍
2016/12/29 Javascript
老生常谈js-react组件生命周期
2017/05/02 Javascript
浅谈原型对象的常用开发模式
2017/07/22 Javascript
ionic2屏幕适配实现适配手机、平板等设备的示例代码
2017/08/11 Javascript
vue项目里面引用svg文件并给svg里面的元素赋值
2020/08/17 Javascript
[46:10]2014 DOTA2国际邀请赛中国区预选赛 CnB VS HGT
2014/05/21 DOTA
python多线程操作实例
2014/11/21 Python
python常见数制转换实例分析
2015/05/09 Python
python数字图像处理之高级形态学处理
2018/04/27 Python
Python装饰器语法糖
2019/01/02 Python
Python 二叉树的层序建立与三种遍历实现详解
2019/07/29 Python
python中类的输出或类的实例输出为这种形式的原因
2019/08/12 Python
基于MATLAB和Python实现MFCC特征参数提取
2019/08/13 Python
python 用struct模块解决黏包问题
2020/11/07 Python
CSS3中线性颜色渐变的一些实现方法
2015/07/14 HTML / CSS
2014年应届大学生毕业自我鉴定
2014/01/31 职场文书
运动会入场词200字
2014/02/15 职场文书
企业节能减排实施方案
2014/03/19 职场文书
中层领导干部群众路线对照检查材料思想汇报
2014/10/02 职场文书
校运会加油稿大全
2015/07/22 职场文书
会议室使用管理制度
2015/08/06 职场文书
浅谈Redis主从复制以及主从复制原理
2021/05/29 Redis
Python实现的扫码工具居然这么好用!
2021/06/07 Python
MySQL 全文检索的使用示例
2021/06/07 MySQL
Python如何导出导入所有依赖包详解
2021/06/08 Python
浅谈Vue的computed计算属性
2022/03/21 Vue.js