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读取xml
Nov 04 Javascript
jquery validate使用攻略 第四步
Jul 01 Javascript
基于jquery实现后台左侧菜单点击上下滑动显示
Apr 11 Javascript
jquery 滚动条事件简单实例
Jul 12 Javascript
JavaScript中instanceof与typeof运算符的用法及区别详细解析
Nov 19 Javascript
学习JavaScript设计模式(多态)
Nov 25 Javascript
javascript+HTML5 Canvas绘制转盘抽奖
May 16 Javascript
利用javascript如何随机生成一定位数的密码
Sep 22 Javascript
微信小程序全局变量改变监听的实现方法
Jul 15 Javascript
js神秘的电报密码 哈弗曼编码实现
Sep 10 Javascript
vue props 一次传多个值实例
Jul 22 Javascript
JavaScript实现复选框全选和取消全选
Nov 20 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/07/03 PHP
PHP中static关键字原理的学习研究分析
2011/07/18 PHP
总结的一些PHP开发中的tips(必看篇)
2017/03/24 PHP
js文字滚动停顿效果代码
2008/06/28 Javascript
javascript语言结构小记(一)
2011/09/10 Javascript
JavaScript中数据结构与算法(五):经典KMP算法
2015/06/19 Javascript
实践中学习AngularJS表单
2016/03/21 Javascript
jQuery实现的导航动画效果(附demo源码)
2016/04/01 Javascript
jQuery 调用WebService 实例讲解
2016/06/28 Javascript
JS封装的选项卡TAB切换效果示例
2016/09/20 Javascript
nodejs进阶(6)—连接MySQL数据库示例
2017/01/07 NodeJs
如何用js判断dom是否有存在某class的值
2017/02/13 Javascript
layui 动态设置checbox 选中状态的例子
2019/09/02 Javascript
vue中使用element ui的弹窗与echarts之间的问题详解
2019/10/25 Javascript
JS实现商城秒杀倒计时功能(动态设置秒杀时间)
2019/12/12 Javascript
通过vue刷新左侧菜单栏操作
2020/08/06 Javascript
如何HttpServletRequest文件对象并储存
2020/08/14 Javascript
[01:52]2014DOTA2西雅图邀请赛 V社开大会你不知道的小秘密
2014/07/08 DOTA
[58:42]DOTA2上海特级锦标赛C组败者赛 Newbee VS Archon第一局
2016/02/27 DOTA
Python实现方便使用的级联进度信息实例
2015/05/05 Python
Python:Scrapy框架中Item Pipeline组件使用详解
2017/12/27 Python
python实现搜索文本文件内容脚本
2018/06/22 Python
python实现图像检索的三种(直方图/OpenCV/哈希法)
2019/08/08 Python
学python安装的软件总结
2019/10/12 Python
用Python去除图像的黑色或白色背景实例
2019/12/12 Python
Matlab使用Plot函数实现数据动态显示方法总结
2021/02/25 Python
俄罗斯美容和健康网上商店:Созвездие Красоты
2019/07/23 全球购物
英国美术用品购物网站:Cass Art
2019/10/08 全球购物
便利店的创业计划书
2014/01/15 职场文书
个人委托书怎么写
2014/04/04 职场文书
教师师德考核自我评价
2014/09/13 职场文书
单位工作证明书格式
2014/10/04 职场文书
员工自我工作评价
2015/03/06 职场文书
2016年会领导致辞稿
2015/07/29 职场文书
团队合作精神学习心得体会
2016/01/19 职场文书
小学英语教学反思范文
2016/02/15 职场文书