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 相关文章推荐
表格单元格交错着色实现思路及代码
Apr 01 Javascript
js有序数组的连接问题
Oct 01 Javascript
js实现点击切换TAB标签实例
Aug 21 Javascript
JS非Alert实现网页右下角“未读信息”效果弹窗
Sep 26 Javascript
KnockoutJS 3.X API 第四章之事件event绑定
Oct 10 Javascript
使用AngularJS2中的指令实现按钮的切换效果
Mar 27 Javascript
移动端触摸滑动插件swiper使用方法详解
Aug 11 Javascript
js 发布订阅模式的实例讲解
Sep 10 Javascript
浅谈Vue.js 组件中的v-on绑定自定义事件理解
Nov 17 Javascript
jQuery实现简单的下拉菜单导航功能示例
Dec 07 jQuery
Node.js使用Angular简单示例
May 11 Javascript
彻底弄懂 JavaScript 执行机制
Oct 23 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中文字符截取防乱码
2008/03/28 PHP
PHP备份数据库生成SQL文件并下载的函数代码
2012/02/05 PHP
windows下apache搭建php开发环境
2015/08/27 PHP
PHP实现删除多重数组对象属性并重新赋值的方法
2017/06/07 PHP
PHP不使用内置函数实现字符串转整型的方法示例
2017/07/03 PHP
数组Array进行原型prototype扩展后带来的for in遍历问题
2010/02/07 Javascript
深入理解JavaScript系列(12) 变量对象(Variable Object)
2012/01/16 Javascript
Js判断CSS文件加载完毕的具体实现
2014/01/17 Javascript
jquery中的ajax方法怎样通过JSONP进行远程调用
2014/05/04 Javascript
javascript实现控制div颜色
2015/07/07 Javascript
AngularJS入门教程之AngularJS指令
2016/04/18 Javascript
web前端开发upload上传头像js示例代码
2016/10/22 Javascript
Javascript基础回顾之(二) js作用域
2017/01/31 Javascript
ES6学习笔记之正则表达式和字符串正则方法分析
2017/04/25 Javascript
微信小程序视图template模板引用的实例详解
2017/09/20 Javascript
微信小程序 wxParse插件显示视频问题
2019/09/27 Javascript
vue 解决data中定义图片相对路径页面不显示的问题
2020/08/13 Javascript
Python回调函数用法实例详解
2015/07/02 Python
python爬虫实现教程转换成 PDF 电子书
2017/02/19 Python
python3+PyQt5泛型委托详解
2018/04/24 Python
python判断设备是否联网的方法
2018/06/29 Python
django框架使用方法详解
2019/07/18 Python
详解python列表(list)的使用技巧及高级操作
2019/08/15 Python
Python实现图片识别加翻译功能
2019/12/26 Python
教你如何用python操作摄像头以及对视频流的处理
2020/10/12 Python
Python解析微信dat文件的方法
2020/11/30 Python
阿迪达斯俄罗斯官方商城:adidas俄罗斯
2017/03/08 全球购物
英国在线药房和在线医生:LloydsPharmacy
2019/10/21 全球购物
美国环保妈妈、儿童和婴儿用品购物网站:The Tot
2019/11/24 全球购物
北京捷通华声语音技术有限公司Java软件工程师笔试题
2012/04/10 面试题
中式婚礼主持词
2014/03/13 职场文书
培养联系人考察意见
2015/06/01 职场文书
企业团队精神心得体会
2016/01/19 职场文书
创业计划书之川味火锅店
2019/09/02 职场文书
PostgreSQL并行计算算法及参数强制并行度设置方法
2022/04/06 PostgreSQL
Mybatis-Plus 使用 @TableField 自动填充日期
2022/04/26 Java/Android