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 定义function的三种方式小结
Oct 16 Javascript
jQuery调用RESTful WCF示例代码(GET方法/POST方法)
Jan 26 Javascript
javascript事件冒泡详解和捕获、阻止方法
Apr 12 Javascript
js中string转int把String类型转化成int类型
Aug 13 Javascript
javascript实现浏览器窗口传递参数的方法
Sep 03 Javascript
BAT及各大互联网公司2014前端笔试面试题--JavaScript篇
Oct 29 Javascript
JS实现网页表格自动变大缩小的方法
Mar 09 Javascript
js实现精确到毫秒的倒计时效果
Aug 05 Javascript
jquery实现刷新随机变化样式特效(tag标签样式)
Feb 03 Javascript
vue中使用GraphQL的实例代码
Nov 04 Javascript
JS实现简易留言板特效
Dec 23 Javascript
vue axios请求成功却进入catch的原因分析
Sep 08 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
全局记录程序片段的运行时间 正确找到程序逻辑耗时多的断点
2011/01/06 PHP
只需20行代码就可以写出CSS覆盖率测试脚本
2013/04/24 Javascript
setTimeout()递归调用不加引号出错的解决方法
2014/09/05 Javascript
Jquery实现遮罩层的方法
2015/06/08 Javascript
使用Node.js为其他程序编写扩展的基本方法
2015/06/23 Javascript
适用于javascript开发者的Processing.js入门教程
2016/02/24 Javascript
requireJS使用指南
2016/04/27 Javascript
JS常用加密编码与算法实例总结
2016/12/22 Javascript
微信小程序 实现动态显示和隐藏某个控件
2017/04/27 Javascript
vue-router实现tab标签页(单页面)详解
2017/10/17 Javascript
JavaScript的setter与getter方法
2017/11/29 Javascript
vue2 前端搜索实现示例
2018/02/26 Javascript
JavaScript实现连连看连线算法
2019/01/05 Javascript
vue通过v-html指令渲染的富文本无法修改样式的解决方案
2020/05/20 Javascript
[00:32]2018DOTA2亚洲邀请赛Mineski出场
2018/04/04 DOTA
python调用其他文件函数或类的示例
2019/07/16 Python
python实现静态服务器
2019/09/05 Python
python实现实时视频流播放代码实例
2020/01/11 Python
Python标准库shutil模块使用方法解析
2020/03/10 Python
基于python实现复制文件并重命名
2020/09/16 Python
Python爬取酷狗MP3音频的步骤
2021/02/26 Python
收集的22款给力的HTML5和CSS3帮助工具
2012/09/14 HTML / CSS
HTML5之SVG 2D入门11—用户交互性(动画)介绍及应用
2013/01/30 HTML / CSS
html5 canvas合成海报所遇问题及解决方案总结
2017/08/03 HTML / CSS
英国二手iPhone、音乐、电影和游戏商店:musicMagpie
2018/10/26 全球购物
5个HTML5的常用本地存储方式详解与介绍
2021/03/27 HTML / CSS
门诊手术室工作制度
2014/01/30 职场文书
迟到检讨书500字
2014/02/05 职场文书
好人好事事迹材料
2014/02/12 职场文书
优乐美广告词
2014/03/14 职场文书
业务员岗位职责范本
2015/04/03 职场文书
国庆放假通知怎么写
2015/07/30 职场文书
2016师德师风学习心得体会
2016/01/12 职场文书
教师反邪教心得体会
2016/01/15 职场文书
先进基层党组织事迹材料2016
2016/02/29 职场文书
CSS实现五种常用的2D转换
2021/12/06 HTML / CSS