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 相关文章推荐
jBox 2.3基于jquery的最新多功能对话框插件 常见使用问题解答
Nov 10 Javascript
JS JSON对象转为字符串的简单实现方法
Nov 18 Javascript
jQuery中:only-child选择器用法实例
Jan 03 Javascript
jQuery实现给页面换肤的方法
May 30 Javascript
JavaScript中实现Map的示例代码
Sep 09 Javascript
简单了解Backbone.js的Model模型以及View视图的源码
Feb 14 Javascript
JS中的二叉树遍历详解
Mar 18 Javascript
JavaScript入门系列之知识点总结
Mar 24 Javascript
jQuery 禁止表单用户名、密码自动填充功能
Oct 30 jQuery
详解Webpack loader 之 file-loader
Nov 07 Javascript
Mint UI组件库CheckList使用及踩坑总结
Dec 20 Javascript
js 将线性数据转为树形的示例代码
May 28 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数组函数序列之rsort() - 对数组的元素值进行降序排序
2011/11/02 PHP
PHP编程函数安全篇
2013/01/08 PHP
浅析PHP原理之变量(Variables inside PHP)
2013/08/09 PHP
thinkphp ajaxfileupload实现异步上传图片的示例
2017/08/28 PHP
关于laravel 日志写入失败问题汇总
2019/10/17 PHP
Web层改进II-用xmlhttp 无声息提交复杂表单
2007/01/22 Javascript
一个关于javascript匿名函数的问题分析
2012/03/30 Javascript
jquery清空表单数据示例分享
2014/02/13 Javascript
JS中实现简单Formatter函数示例代码
2014/08/19 Javascript
JavaScript的字符串方法汇总
2016/07/31 Javascript
jQuery File Upload文件上传插件使用详解
2016/12/06 Javascript
BootStrap中
2016/12/10 Javascript
微信小程序 radio单选框组件详解及实例代码
2017/01/10 Javascript
PHP实现本地图片上传和验证功能
2017/02/27 Javascript
webpack踩坑之路图片的路径与打包
2017/09/05 Javascript
Vue打包后出现一些map文件的解决方法
2018/02/13 Javascript
Vue 开发音乐播放器之歌手页右侧快速入口功能
2018/08/08 Javascript
Vue使用预渲染代替SSR的方法
2020/07/02 Javascript
vue 实现click同时传入事件对象和自定义参数
2021/01/29 Vue.js
[01:09]2014DOTA2国际邀请赛 TI4西雅图DOTA2 中国美女coser加油助威
2014/07/20 DOTA
详解Python下载图片并保存本地的两种方式
2019/05/15 Python
django用户登录验证的完整示例代码
2019/07/21 Python
Python 3.8正式发布重要新功能一览
2019/10/17 Python
利用python实现逐步回归
2020/02/24 Python
css3 盒模型以及box-sizing属性全面了解
2016/09/20 HTML / CSS
美国购买汽车零件网站:Buy Auto Parts
2018/04/02 全球购物
Java如何获得ResultSet的总行数
2016/09/03 面试题
回门宴答谢词
2014/01/13 职场文书
建议书怎么写
2014/03/12 职场文书
房屋租赁协议书
2014/10/18 职场文书
2015年环保局工作总结
2015/05/22 职场文书
《认识年月日》教学反思
2016/02/19 职场文书
Pyhton模块和包相关知识总结
2021/05/12 Python
Python爬虫之用Xpath获取关键标签实现自动评论盖楼抽奖(二)
2021/06/07 Python
使用ORM新增数据在Mysql中的操作步骤
2021/07/26 MySQL
JavaScript实现音乐播放器
2022/08/14 Javascript