最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 【译】JS中的面向切面编程

    正文概述 掘金(智云健康大前端团队)   2020-12-08   559

    原文地址:blog.bitsrc.io/aspect-orie…

    译者:Gavin,未经授权禁止转载。

    前言

    写JS的同学应该都听说过面向对象程序设计(OOP)与函数式编程(FP),对Java或nestjs有一些了解的同学应该也听说过面向切面的程序设计(AOP),但你知道通过原生JS怎么去实现一个最简的AOP功能吗?

    幸运的是,就像JS中的OOP与FP一样,你可以毫不费力的将AOP与FP或OOP混用。

    AOP简介

    AOP为我们提供了一种不需要修改现有逻辑将代码注入到现有函数或对象中的方法。

    AOP切面实现的3要素

    • Aspect:切面,用于封装要添加的行为
    • Advice:通知(增强),它指定了希望执行代码的常见时刻,如:beforeafteraroundwhen throwing
    • Pointcut:切入点,用于指明在具体需要进行方法增强的位置,比如:某个特殊的方法某个对象下的所有方法

    基本实现

    下面示例用于说明实现AOP的容易程度及其给代码带来的好处。

    // 源文件地址:https://gist.github.com/deleteman/1b73da25feabf32db33c611674eb1ca6#file-aop-js
    
    // aop.js
    /** 用于获取对象上所有的方法 */
    const getMethods = (obj) => Object.getOwnPropertyNames(Object.getPrototypeOf(obj)).filter(item => typeof obj[item] === 'function')
    
    /** 用于在特殊时刻利用自定义函数替换原始方法 */
    function replaceMethod(target, methodName, aspect, advice) {
        const originalCode = target[methodName]
        target[methodName] = (...args) => {
            if(["before", "around"].includes(advice)) {
                aspect.apply(target, args)
            }
            const returnedValue = originalCode.apply(target, args)
            if(["after", "around"].includes(advice)) {
                aspect.apply(target, args)
            }
            if("afterReturning" == advice) {
                return aspect.apply(target, [returnedValue])
            } else {
                return returnedValue
            }
        }
    }
    
    module.exports = {
        // 用于在需要的时刻和位置将注入切面功能
        inject: function(target, aspect, advice, pointcut, method = null) {
            if(pointcut == "method") {
                if(method != null) {
                    replaceMethod(target, method, aspect, advice)    
                } else {
                    throw new Error("Tryin to add an aspect to a method, but no method specified")
                }
            }
            if(pointcut == "methods") {
                const methods = getMethods(target)
                methods.forEach( m => {
                    replaceMethod(target, m, aspect, advice)
                })
            }
        } 
    }
    
    // 源文件地址:https://gist.github.com/deleteman/1efd939193400a569308945eb445e3cd#file-using-aop-js
    
    // using-aop.js
    const AOP = require("./aop.js")
    
    class MyBussinessLogic {
        add(a, b) {
            console.log("Calling add")
            return a + b
        }
    
        concat(a, b) {
            console.log("Calling concat")
            return a + b
        }
    
        power(a, b) {
            console.log("Calling power")
            return a ** b
        }
    }
    
    const o = new MyBussinessLogic()
    
    function loggingAspect(...args) {
        console.log("== Calling the logger function ==")
        console.log("Arguments received: " + args)
    }
    
    function printTypeOfReturnedValueAspect(value) {
        console.log("Returned type: " + typeof value)
    }
    
    AOP.inject(o, loggingAspect, "before", "methods")
    AOP.inject(o, printTypeOfReturnedValueAspect, "afterReturning", "methods")
    
    o.add(2,2)
    o.concat("hello", "goodbye")
    o.power(2, 3)
    

    上面代码很简单,一个基本对象有3个方法。其中包含两个注入切面,一个用于记录接受到的属性,另一个用于分析其返回值并记录其类型。最终输出:

    【译】JS中的面向切面编程

    AOP的好处

    • 封装横切关注点:封装横切关注点有利于阅读和维护整个项目
    • 灵活的逻辑:当涉及到切面注入时,围绕通知(增强)和切入点实现的逻辑可以提供很大的灵活性
    • 跨项目重用:可以将切面视为组件,即可以在任何地方运行小而分离的代码片段,可以轻松在不同项目中共享使用

    AOP的主要问题

    • 隐藏逻辑性与复杂性:用函数式编程的思维讲AOP具有副作用,它可以向现有的方法中添加不相关的行为,甚至可以替换原有方法的整个逻辑

    总结

    AOP提供了做任何想做事情的能力,如果缺乏良好的编程实践,可以导致非常大的代码混乱。简单总结就是权力越大,责任越大。如果想正确地使用AOP,那么首先必须得理解其核心思想和最佳实践。

    AOP是OOP的完美补充,由于JS的动态特性,我们可以非常容易的实现它。同时它也提供了强大的功能,模块化和解耦大量逻辑的能力,甚至可以轻松实现跨项目的逻辑共享。

    但如果不正确的使用,可能也会造成大量的代码混乱。

    相关链接(译者注)

    • nestjs中参考AOP技术的实现
    • 在eggjs中实践依赖注入与面向切面编程

    起源地下载网 » 【译】JS中的面向切面编程

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元