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 表单下所有元素的隐藏
Jul 25 Javascript
DOM基础教程之模型中的模型节点
Jan 19 Javascript
jquery实现鼠标滑过显示提示框的方法
Feb 05 Javascript
AngularJS学习笔记之ng-options指令
Jun 16 Javascript
jQuery 3.0 的 setter和getter 模式详解
Jul 11 Javascript
利用jQuery插件imgAreaSelect实现图片上传裁剪(放大缩小)
Dec 02 Javascript
node.js 和HTML5开发本地桌面应用程序
Dec 13 Javascript
JS实现PC手机端和嵌入式滑动拼图验证码三种效果
Feb 15 Javascript
vue-cli3.0 特性解读
Apr 22 Javascript
vue 属性拦截实现双向绑定的实例代码
Oct 24 Javascript
vuex分模块后,实现获取state的值
Jul 26 Javascript
vue自动添加浏览器兼容前后缀操作
Aug 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 MYSQL中插入当前时间
2008/04/06 PHP
php 缓存函数代码
2008/08/27 PHP
PHP生成(支持多模板)二维码海报代码
2018/04/30 PHP
thinkphp5实现无限级分类
2019/02/18 PHP
ThinkPHP5.1+Ajax实现的无刷新分页功能示例
2020/02/10 PHP
javascript 清空form表单中某种元素的值
2009/12/26 Javascript
裁剪字符串trim()自定义改进版
2013/04/10 Javascript
Extjs4 Treegrid 使用心得分享(经验篇)
2013/07/01 Javascript
jquery 使用简明教程
2014/03/05 Javascript
JavaScript实现带标题的图片轮播特效
2015/05/20 Javascript
JS中跨页面调用变量和函数的方法(例如a.js 和 b.js中互相调用)
2016/11/01 Javascript
nodeJs链接Mysql做增删改查的简单操作
2017/02/04 NodeJs
jQuery实现百度图片移入移出内容提示框上下左右移动的效果
2018/06/05 jQuery
vue 配置多页面应用的示例代码
2018/10/22 Javascript
js中let能否完全替代IIFE
2019/06/15 Javascript
javascript中this的用法实践分析
2019/07/29 Javascript
利用js canvas实现五子棋游戏
2020/10/11 Javascript
微信小程序实现分页加载效果
2020/11/19 Javascript
Python正则表达式匹配ip地址实例
2014/10/09 Python
Python实现学校管理系统
2018/01/11 Python
Django框架之中间件MiddleWare的实现
2019/12/30 Python
在django中使用apscheduler 执行计划任务的实现方法
2020/02/11 Python
python+adb+monkey实现Rom稳定性测试详解
2020/04/23 Python
如何使用 Python 读取文件和照片的创建日期
2020/09/05 Python
python 如何实现遗传算法
2020/09/22 Python
如何基于Python按行合并两个txt
2020/11/03 Python
竞聘副主任科员演讲稿
2014/01/11 职场文书
风险评估实施方案
2014/03/09 职场文书
小学语文教学经验交流材料
2014/06/02 职场文书
教师批评与自我批评材料
2014/10/16 职场文书
医学生自荐信范文
2015/03/05 职场文书
教师节获奖感言
2015/07/31 职场文书
2016学校元旦晚会经典开场白台词
2015/12/03 职场文书
2016年5月份红领巾广播稿
2015/12/21 职场文书
python之np.argmax()及对axis=0或者1的理解
2021/06/02 Python
vue中的可拖拽宽度div的实现示例
2022/04/08 Vue.js