高阶函数实现AOP

180 阅读2分钟

概况

在我们前端开发过程中,需要对某些业务逻辑进行前置监控、和后置监控。这个时候我们就会用到了AOP(面向切面编程),主要就是吧一些跟核心业务逻辑模块无关的功能抽离出来,这些跟业务逻辑无关的功能包括日志统计、安全控制、异常处理等。把这些功能更抽离出来之后,在通过“动态植入”的方式插入业务逻辑模块中。 这样做的好处是首先可以保证业务逻辑模块的纯净和高内聚性,其次是可以很方便得复用日志统计等功能模块。

>所谓的AOP就是在执行原业务逻辑的前后插入,2段代码逻辑,从而实现函数的动态植入
// 原来
fn()

// 植入后
fn_before()
fn()
fn_after()

代码讲解过程:

        Function.prototype.before = function (callback){
            var _that = this
            // 这里的this是谁,要看,是谁调用了before,由下面代码知道是fn调用了before,所以this = fn
            return function(){
                callback()
                _that()
            }
        }
		// fn 是有Function实例化之后的一个对象
        var fn = function () {
            console.log('最原始函数')
        }
        var newFn =  fn.before(()=>{
            console.log('fn-之前执行')
        })
        
        newFn()
        // fn-之前执行
        // 最原始函数

优化:

        Function.prototype.before = function (beforeFn){
            var _self = this
            return function(){
                beforeFn.apply(this,arguments)
                return _self.apply(this,arguments)
            }
        }
        var fn = function () {
            console.log('最原始函数')
        }
        var newFn =  fn.before(()=>{
            console.log('fn-之前执行')
        })
        newFn()
        // fn-之前执行
        // 最原始函数

在优化( 加入后置函数 )

        Function.prototype.before = function (beforeFn){
            var _self = this
            return function(){
                beforeFn.apply(this,arguments)
                return _self.apply(this,arguments)
            }
        }
        Function.prototype.after = function (afterFn){
            var _self = this
            // 注意:这里的this只带的是最后调用after
            // 也就是执行完fn.before(()=>{})之后,调用的
            // 而执行fn.before(()=>{})返回了一个function(){}
            // 也就是最后返回的 function 调用了after,既this 就是 这个function 
            /*  function(){
                    beforeFn.apply(this,arguments)
                    return _self.apply(this,arguments)
            } */
            return function(){
                var ret = _self.apply(this,arguments)
                afterFn.apply(this.arguments)
                return ret
            }
        }
        var fn = function () {
            console.log('最原始函数')
        }
        var newFn =  fn.before(()=>{
            console.log('fn-之前执行')
        }).after(function(){
            console.log('fn-之后执行')
        })
        newFn()
        // fn-之前执行
        // 最原始函数
        // fn-之后执行