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基本类型和引用类型
Dec 09 Javascript
深入理解Node.js的HTTP模块
Oct 12 Javascript
基于JavaScript实现自定义滚动条
Jan 25 Javascript
使用bootstrap-paginator.js 分页来进行ajax 异步分页请求示例
Mar 09 Javascript
利用 spin.js 生成等待效果(js 等待效果)
Jun 25 Javascript
详解如何使用webpack在vue项目中写jsx语法
Nov 08 Javascript
p5.js入门教程之鼠标交互的示例
Mar 16 Javascript
关于JavaScript中高阶函数的魅力详解
Sep 07 Javascript
vue如何安装使用Quill富文本编辑器
Sep 21 Javascript
Vue路由切换页面不更新问题解决方案
Jul 10 Javascript
解决vue安装less报错Failed to compile with 1 errors的问题
Oct 22 Javascript
Vue-router中hash模式与history模式的区别详解
Dec 15 Vue.js
使用 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中的超全局变量
2006/10/09 PHP
php实现删除指定目录下相关文件的方法
2014/10/20 PHP
php实现网站留言板功能
2015/11/04 PHP
浅析PHP中call user func()函数及如何使用call user func调用自定义函数
2015/11/05 PHP
PHP文件缓存smarty模板应用实例分析
2016/02/26 PHP
php实现的错误处理封装类实例
2017/06/20 PHP
PHP实现的自定义图像居中裁剪函数示例【测试可用】
2017/08/11 PHP
js文件中调用js的实现方法小结
2009/10/23 Javascript
jQuery 常见开发使用技巧总结
2009/12/26 Javascript
ExtJs使用IFrame的实现代码
2010/03/24 Javascript
基于prototype扩展的JavaScript常用函数库
2010/11/30 Javascript
JavaScript基础语法让人疑惑的地方小结
2012/05/23 Javascript
使用JS获取当前地理位置方法汇总
2014/12/18 Javascript
微信小程序如何使用canvas二维码保存至手机相册
2019/07/15 Javascript
聊聊鉴权那些事(推荐)
2019/08/22 Javascript
详解VUE中的插值( Interpolation)语法
2020/10/18 Javascript
Vue中computed和watch有哪些区别
2020/12/19 Vue.js
使用Python的Django框架实现事务交易管理的教程
2015/04/20 Python
Pyhthon中使用compileall模块编译源文件为pyc文件
2015/04/28 Python
Python 多线程Threading初学教程
2017/08/22 Python
Python3调用微信企业号API发送文本消息代码示例
2017/11/10 Python
python基础练习之几个简单的游戏
2017/11/10 Python
python的Crypto模块实现AES加密实例代码
2018/01/22 Python
实例详解python函数的对象、函数嵌套、名称空间和作用域
2019/05/31 Python
python如何实现代码检查
2019/06/28 Python
Python 中的函数装饰器和闭包详解
2021/02/06 Python
美国玛丽莎收藏奢华时尚商店:Marissa Collections
2016/11/21 全球购物
英国PC组件和在线电脑商店:SCAN
2019/04/18 全球购物
工作交流会欢迎词
2014/01/12 职场文书
计算机专业职业生涯规划范文
2014/01/19 职场文书
经典商业广告词
2014/03/13 职场文书
成龙洗发水广告词
2014/03/14 职场文书
机械设计及其自动化专业求职信
2014/06/09 职场文书
总经理岗位职责说明书
2014/07/30 职场文书
Java org.w3c.dom.Document 类方法引用报错
2021/08/07 Java/Android
MongoDB使用场景总结
2022/02/24 MongoDB