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 相关文章推荐
js控制input输入字符解析
Dec 27 Javascript
js调试工具Console命令详解
Oct 21 Javascript
极易被忽视的javascript面试题七问七答
Feb 15 Javascript
JavaScript中ES6字符串扩展方法
Aug 26 Javascript
jQuery插件HighCharts绘制2D半圆环图效果示例【附demo源码下载】
Mar 09 Javascript
详解用vue编写弹出框组件
Jul 04 Javascript
小程序实现带年月选取效果的日历
Jun 27 Javascript
浅谈Vue.js 关于页面加载完成后执行一个方法的问题
Apr 01 Javascript
微信小程序实现时间进度条功能
Nov 17 Javascript
jQuery实现电梯导航模块
Dec 22 jQuery
js实现简单的倒计时
Jan 28 Javascript
Javascript webpack动态import
Apr 19 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 输出简单动态WAP页面
2009/06/09 PHP
php中的静态变量的基本用法
2014/03/20 PHP
php使用PDO方法详解
2014/12/27 PHP
php限制ip地址范围的方法
2015/03/31 PHP
wordpress安装过程中遇到中文乱码的处理方法
2015/04/21 PHP
yii 框架实现按天,月,年,自定义时间段统计数据的方法分析
2020/04/04 PHP
通过PHP实现获取访问用户IP
2020/05/09 PHP
IE下js调试工具Companion.JS
2010/10/15 Javascript
JavaScript 拾碎[三] 使用className属性
2010/10/16 Javascript
利用谷歌地图API获取点与点的距离的js代码
2012/10/11 Javascript
Bootstrap实现响应式导航栏效果
2015/12/28 Javascript
Vuejs第六篇之Vuejs与form元素实例解析
2016/09/05 Javascript
ReactNative Image组件使用详解
2017/08/07 Javascript
JS+HTML5 Canvas实现简单的写字板功能示例
2018/08/30 Javascript
Webstorm2016使用技巧(SVN插件使用)
2018/10/29 Javascript
Angular7创建项目、组件、服务以及服务的使用
2019/02/19 Javascript
Vue学习之常用指令实例详解
2020/01/06 Javascript
VUE子组件向父组件传值详解(含传多值及添加额外参数场景)
2020/09/01 Javascript
Python遍历指定文件及文件夹的方法
2015/05/09 Python
使用Pyinstaller的最新踩坑实战记录
2017/11/08 Python
分享6个隐藏的python功能
2017/12/07 Python
详解python运行三种方式
2019/05/13 Python
python 读写文件包含多种编码格式的解决方式
2019/12/20 Python
Python标准库:内置函数max(iterable, *[, key, default])说明
2020/04/25 Python
Python基于pandas爬取网页表格数据
2020/05/11 Python
Python使用struct处理二进制(pack和unpack用法)
2020/11/12 Python
html5本地存储 localStorage操作使用详解
2016/09/20 HTML / CSS
英国景点门票网站:attractiontix
2019/08/27 全球购物
UNIX操作系统结构由哪几部分组成
2016/02/17 面试题
2014两会学习心得:时代的发展
2014/03/17 职场文书
个人三严三实对照检查材料思想汇报
2014/09/22 职场文书
2015年业务员工作总结范文
2015/04/07 职场文书
红色革命电影观后感
2015/06/18 职场文书
Python人工智能之混合高斯模型运动目标检测详解分析
2021/11/07 Python
「女孩的钓鱼慢活」全新版权绘公布
2022/03/21 日漫
《勇者辞职不干了》ED主题曲无字幕动画MV公开
2022/04/13 日漫