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 validation插件表单验证的一个例子
Mar 03 Javascript
Node.js与PHP、Python的字符处理性能对比
Jul 06 Javascript
JQuery中$(document)是什么意思有什么作用
Jul 21 Javascript
JavaScript中apply方法的应用技巧小结
Sep 29 Javascript
jsonp跨域请求详解
Jul 13 Javascript
jQuery获取table表中的td标签(实例讲解)
Jul 28 jQuery
Bootstrap 树控件使用经验分享(图文解说)
Nov 06 Javascript
简易Vue评论框架的实现(父组件的实现)
Jan 08 Javascript
[原创]js实现保存文本框内容为本地文件兼容IE,chrome,火狐浏览器
Feb 14 Javascript
教你30秒发布一个TypeScript包到NPM的方法步骤
Jul 22 Javascript
vue实现拖拽的简单案例 不超出可视区域
Jul 25 Javascript
vue动态渲染svg、添加点击事件的实现
Mar 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
php的ajax简单实例
2014/02/27 PHP
PHP批量生成图片缩略图的方法
2015/06/18 PHP
详解PHP的Yii框架的运行机制及其路由功能
2016/03/17 PHP
CI框架中类的自动加载问题分析
2016/11/21 PHP
PHP+AJAX 投票器功能
2017/11/11 PHP
thinkPHP框架自动填充原理与用法分析
2018/04/03 PHP
PHP xpath提取网页数据内容代码解析
2020/07/16 PHP
兼容ie、firefox的图片自动缩放的css跟js代码分享
2012/01/21 Javascript
仿百度联盟对联广告实现代码
2014/08/30 Javascript
javascript中var的重要性分析
2015/02/11 Javascript
JQuery跳出each循环的方法
2015/04/16 Javascript
基于javascript实现全屏漂浮广告
2016/03/31 Javascript
js获取对象、数组的实际长度,元素实际个数的实现代码
2016/06/08 Javascript
Bootstrap表单布局
2016/07/19 Javascript
解析Vue2.0双向绑定实现原理
2017/02/23 Javascript
ComboBox(下拉列表框)通过url加载调用远程数据的方法
2017/08/06 Javascript
vue实现移动端图片裁剪上传功能
2020/08/18 Javascript
浅谈React中的元素、组件、实例和节点
2018/02/27 Javascript
深入浅析Vue中mixin和extend的区别和使用场景
2019/08/01 Javascript
[03:26]回顾2015国际邀请赛中国区预选赛
2015/06/09 DOTA
python与C互相调用的方法详解
2017/07/14 Python
Python基于回溯法子集树模板解决野人与传教士问题示例
2017/09/11 Python
python导出chrome书签到markdown文件的实例代码
2017/12/27 Python
pycharm远程linux开发和调试代码的方法
2018/07/17 Python
对Python中list的倒序索引和切片实例讲解
2018/11/15 Python
python儿童学游戏编程知识点总结
2019/06/03 Python
python 实现turtle画图并导出图片格式的文件
2019/12/07 Python
Python开发之pip安装及使用方法详解
2020/02/21 Python
python 比较字典value的最大值的几种方法
2020/04/17 Python
Python发送邮件封装实现过程详解
2020/05/09 Python
viagogo波兰票务平台:演唱会、体育比赛、戏剧门票
2018/04/23 全球购物
厂长岗位职责
2014/02/19 职场文书
农村葬礼主持词
2014/03/31 职场文书
幼儿园个人师德总结
2015/02/06 职场文书
2019年工作总结范文
2019/05/21 职场文书
Redis之RedisTemplate配置方式(序列和反序列化)
2022/03/13 Redis