看见个好玩的东西 在不改变的原函数的情况下,使原函数输出别的东西
搜了半天,感觉这个东西就是和原型有关的东西 ,用的原型的一个参数吧
代码:
<script> Function.prototype.before = function (beforefn) { var _self = this; //保存原函数引用 return function () { //返回包含了原函数和新函数的"代理函数" beforefn.apply(this, arguments); //执行新函数,修正this return _self.apply(this, arguments); //执行原函数 } }; Function.prototype.after = function (afterfn) { var _self = this; return function () { var ret = _self.apply(this, arguments); afterfn.apply(this, arguments); return ret; } }; var func = function () { console.log("2") } func = func.before(function () { console.log("1"); }).after(function () { console.log("3"); } ) func(); </script>
原理了解下:
AOP在JS中的实现及应用
原文链接:https://blog.csdn.net/qq_21460229/article/details/79696159
AOP (面向切面编程),缩写为Aspect Oriented Programming,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是JAVA 中Spring框架的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
注:请慎重的在JS的中使用AOP!因为部分JS的方法是异步的。
必要时使用ES7中的async/await/Promise,以保证代码的顺序执行。
2.AOP在JS中的实现原理
js中aop的实现原理主要依靠Function
的两个函数:apply
和call
。
apply
函数
apply方法能劫持另外一个对象的方法,继承另外一个对象的属性
Function.apply(obj, args)方法能接收两个参数
obj:这个对象将代替Function类里this对象
args:这个是数组,它将作为参数传给Function(args–>arguments)
利用Function.apply()的参数数组化来提升程序的性能
function dosomething(a,b,c){ console.log('do something.', a, b, c); // 预期结果: do something. see say run } let something = ['see', 'say', 'run']; dosomething.apply(this, something); ————————————————
call
函数
Function.call(obj, arg, arg, ...);
function dosomething(a,b,c){ console.log('do something.', a, b, c); // 预期结果: do something. see say run } dosomething.call(this, 'see', 'say', 'run');
推荐:使用apply函数。call函数和apply函数的效果是一样,但是call函数的参数不够灵活,在写法上参数无法灵活伸缩;apply函数,只需要把参数放到数组里即可。apply比call函数更适合在项目实际开发中使用,并且apply比call的性能要好。
3.AOP在JS中的实现
从事过Java Web开发的童鞋,一定用过Spring框架。在Spring的框架中有before
(前置通知)、after
(后置通知)、around
(环绕通知)。
今天我们在JS中实现的这三种通知。
1. before(前置通知)
before
函数,用来实现函数的前置通知。在目标函数的前面执行一些前置操作。
// AOP 前置通知函数声明 /** * 给方法加入前置切片函数 * 可以在执行方法之前执行一些操作, * 前置切片的返回值为false时,不影响原方法的执行 * @param func {Function} 被前置执行的函数 * @return {Function} 加入前置通知的函数 */ Function.prototype._before = function(func){ var __self = this; return function(){ func.apply(__self, arguments); return __self.apply(__self, arguments); } } // 代码 function a(){ console.log('I\'m a'); } a = a._before(function(){ console.log('before'); }); a(); // 结果: // before // I'm a
2. after(后置通知)
after
函数,用来实现函数的后置通知。在目标函数的后面面执行一些后置操作。
// AOP 后置通知函数声明 /** * 给方法加入后置切片函数 * 可以在执行方法之之后执行一些操作 * 后置切片的返回值为false时,不影响原方法的执行 * @param func {Function} 被后置执行的函数 * @return {Function} 加入后置通知的函数 * @constructor */ Function.prototype._after = function(func){ var __self = this; return function(){ var ret = __self.apply(__self, arguments); func.apply(__self, arguments); return ret; } } // 代码 function b(){ console.log('I\'m b'); } b = b._after(function(){ console.log('after'); }); b(); // 结果: // I'm b // after
3. around(环绕通知)
在around函数中,引入了一个JoinPoint对象。JoinPoint对象封装了目标函数和目标函数的参数。在调用JoinPoint对象的invoke函数时,会去调用原来的目标函数。在调用invoke时,如果需要改变目标函数的this对象,需要将对象传入到invoke的参数中。around函数,可以在目标函数的前面和后面随意加入逻辑代码,也可以根据条件判断是否执行目标函数。
// AOP 环绕通知函数声明 /** * 切入点对象 * 不允许切入对象多次调用 * @param obj 对象 * @param args 参数 * @constructor */ function JoinPoint(obj, args){ var isapply = false; // 判断是否执行过目标函数 var result = null; // 保存目标函数的执行结果 this.source = obj; // 目标函数对象 this.args = args; // 目标函数对象传入的参数 /** * 目标函数的代理执行函数 * 如果被调用过,不能重复调用 * @return {object} 目标函数的返回结果 */ this.invoke = function(thiz){ if(isapply){ return; } isapply = true; result = this.source.apply(thiz || this.source, this.args); return result; }; // 获取目标函数执行结果 this.getResult = function(){ return result; } } /** * 方法环绕通知 * 原方法的执行需在环绕通知方法中执行 * @param func {Function} 环绕通知的函数 * 程序会往func中传入一个JoinPoint(切入点)对象, 在适当的时机 * 执行JoinPoint对象的invoke函数,调用目标函数 * * @return {Function} 切入环绕通知后的函数, */ Function.prototype._around = function(func){ var __self = this; return function(){ var args = [new JoinPoint(__self, arguments)]; return func.apply(this, args); } } // 代码 var isAdmin = true; function c(){ console.log('show user list'); } c = c._around(function(joinpoint){ if(isAdmin){ // 满足条件时,执行目标函数 console.log('is admin'); joinpoint.invoke(this); } }); c(); // 结果 // if isAdmin == true // is admin // show user list // if isAdmin == false //
4.AOP在JS中的应用
AOP在数据库方面的应用
- 记录sql的执行记录(AOP的前置通知)
- 记录sql的执行时间(AOP的环绕通知)
- sql执行完后自动释放连接(AOP的环绕通知)
原文地址:https://www.cnblogs.com/lhqdbk/p/11731912.html
- 归并排序算法的编码和优化
- Kotlin语法基础之运算符
- Kotlin语法基础之控制流
- Kotlin 包和 import 语句使用
- 使用多个Target去管理项目版本环境
- Facebook iOS UI 工具ComponentKit简介
- 基于OpenCV的跳一跳外挂实现原理
- React Native 0.50版本新功能简介
- Android滤镜效果实现及原理分析
- Spring Boot入门及整合mybatis
- Swift开发React Native组件
- 深入理解Android插件化技术
- Kotlin DSL详解
- 大规模异常滥用检测:基于局部敏感哈希算法——来自Uber Engineering的实践
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2)C. The Phone Number
- Codeforces Beta Round #3 C. Tic-tac-toe
- [记录] 数据库中,根据经纬度,查询距离最近的地点
- PAT (Basic Level) Practice (中文)1010 一元多项式求导 (25 分)
- R语言随机森林模型中具有相关特征的变量重要性
- PAT (Basic Level) Practice (中文)1009 说反话 (20 分)
- Codeforces Beta Round #8 A. Train and Peter
- Codeforces Round #559 (Div. 2)B. Expansion coefficient of the array
- Codeforces Beta Round #72 (Div. 1 Only)B. Doctor
- pygame游戏常用方法
- node-blog:用 node 搭建的个人开源博客
- 2018-2019 ICPC, NEERC, Southern Subregional Contest D. Garbage Disposal
- 「查缺补漏」JavaScript执行上下文-执行栈
- 树状数组 _ 求逆序数
- PAT (Basic Level) Practice (中文)1012 数字分类 (20 分)