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 jqgrid 对含特殊字符json 数据的 Java 处理方法
Jan 01 Javascript
在浏览器中获取当前执行的脚本文件名的代码
Jul 19 Javascript
js实现仿qq消息的弹出窗效果
Jan 06 Javascript
jQuery获取table下某一行某一列的值实现代码
Apr 07 jQuery
js获取一组日期中最近连续的天数
May 25 Javascript
详解express + mock让前后台并行开发
Jun 06 Javascript
vue2.0 如何在hash模式下实现微信分享
Jan 22 Javascript
JavaScript实现的拼图算法分析
Feb 13 Javascript
详解element-ui中表单验证的三种方式
Sep 18 Javascript
node.js文件操作系统实例详解
Nov 05 Javascript
JavaScript console的使用方法实例分析
Apr 28 Javascript
Map与WeakMap类型在JavaScript中的使用详解
Nov 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/05/06 PHP
PHP FOR MYSQL 代码生成助手(根据Mysql里的字段自动生成类文件的)
2011/07/23 PHP
解析:通过php socket并借助telnet实现简单的聊天程序
2013/06/18 PHP
PHP 冒泡排序 二分查找 顺序查找 二维数组排序算法函数的详解
2013/06/25 PHP
php数组使用规则分析
2015/02/27 PHP
Ajax PHP JavaScript MySQL实现简易无刷新在线聊天室
2016/08/17 PHP
prototype class详解
2006/09/07 Javascript
JS加ASP二级域名转向的代码
2007/05/17 Javascript
javascript学习笔记(十六) 系统对话框(alert、confirm、prompt)
2012/06/20 Javascript
jquery设置text的值示例(设置文本框 DIV 表单值)
2014/01/06 Javascript
javascript跨浏览器的属性判断方法
2014/03/16 Javascript
js带点自动图片轮播幻灯片特效代码分享
2015/09/07 Javascript
详解JavaScript语言的基本语法要求
2015/11/20 Javascript
JS获取鼠标坐标位置实例分析
2016/01/20 Javascript
Node.js中JavaScript操作MySQL的常用方法整理
2016/03/01 Javascript
JS代码随机生成姓名、手机号、身份证号、银行卡号
2016/04/27 Javascript
jquery做个日期选择适用于手机端示例
2017/01/10 Javascript
React Native之TextInput组件解析示例
2017/08/22 Javascript
微信小程序调用微信支付接口的实现方法
2019/04/29 Javascript
vue解决使用$http获取数据时报错的问题
2019/10/30 Javascript
举例讲解Python中的算数运算符的用法
2015/05/13 Python
详解Python中用于计算指数的exp()方法
2015/05/14 Python
Python cookbook(数据结构与算法)将名称映射到序列元素中的方法
2018/03/22 Python
python3+PyQt5实现自定义流体混合窗口部件
2018/04/24 Python
python将txt等文件中的数据读为numpy数组的方法
2018/12/22 Python
python实现计算器功能
2019/10/31 Python
PHP基于phpqrcode类库生成二维码过程解析
2020/05/28 Python
使用phonegap检测网络状态的方法
2017/03/30 HTML / CSS
Jacadi Paris美国官方网站:法国童装品牌
2017/10/15 全球购物
临床医学专业毕业生的自我评价
2013/10/17 职场文书
如何做好总经理助理
2013/11/12 职场文书
年会活动策划方案
2014/01/23 职场文书
高校教师岗位职责
2014/03/18 职场文书
质量负责人任命书
2014/06/06 职场文书
2015年行政人事工作总结
2015/05/21 职场文书
详解Java实现设计模式之责任链模式
2021/06/23 Java/Android