前端装饰器

本文探讨了JavaScript中的装饰器,作为一种不侵入原有代码的修饰手段,它能够为类、方法和属性添加额外行为。通过实例解释了如何使用装饰器来扩展方法的功能,如在`run`方法中添加输出速度的逻辑,同时介绍了装饰器的实现原理,包括获取和修改对象属性的方法。文章还预告了对ES7中Decorator的进一步讨论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、javascript中的装饰器

装饰器是对类、方法、属性的修饰,增加额外的行为。装饰器不侵入,所以对原先的内容不会破坏。装饰器可以理解成一种解决问题的通用思路,装饰器模式遇到程序之后诞生了多种多样的表现形式。javascript也引入了装饰器这一实验内容,在typescript中已经有使用的案例。

这篇博客记录方法的装饰器,先梳理下装饰器的思路。比如有一个run方法,原先的run方法只是简单输出I am running。

class Run {
    constructor() {

    }
    run() {
        console.log( 'I am running' );
    }

}

接着,希望run方法能输出跑步的速度。最直接的方法是修改Run的run方法,输出速度。我们采用另外一种思路,形式上不修改Run。主要是通过Object.getOwnPropertyDescriptor获取类的方法属性,并修改方法,最后使用Object.defineProperty覆盖原先的方法。


function decorateFunc( Cls, funcNm ) {

    // 获取需要包装的target

    let target = Cls.prototype;

    // 获取属性的descriptor

    let descriptor = Object.getOwnPropertyDescriptor( target, funcNm );

    // 装饰函数

    let decoratedFunc = function ( ...args ) {

        let speed = 12;

        descriptor.value.apply( target, args ); // 执行原来的函数

        console.log( `my speed is ${ speed }` ); // 增加新特性

    }

    // 改写原来的内容

    //Object.defineProperty( target, funcNm, {

    //    ...descriptor,

     //   value: decoratedFunc

    //} );

}

decorateFunc( Run, 'run' );

let target = new Run();

target.run();// I am running my speed is 12

装饰器获取run方法之后执行,并增加了行为,我们还可以再封装一次,可以增加不同的行为。

//target descriptor key

function wrap( decorator ) {

    return function ( Cls, funcNm ) {

        let target = Cls.prototype;

        let descriptor = Object.getOwnPropertyDescriptor( target, funcNm );

        decorator( target, funcNm, descriptor )

    }

}

let runSpeed = function ( target, funcNm, descriptor ) {

    let speed = 12;

    descriptor.value.apply(target,[]);
    
    console.log(`my speed is ${speed}`);

}

let runDecorator = wrap( runSpeed );

runDecorator( Run, 'run' );

new Run().run();

wrap的参数是函数,函数是用于装饰的函数,装饰用的函数需要目标对象,装饰的函数名称,装饰函数的descriptor。

2、ES7中的Decorator

------------------------------------未完待续----------------------------------

 

### 前端 JavaScript 装饰器设计模式详解 #### 定义与概述 装饰器模式属于一种结构型设计模式,允许向对象添加新功能而不改变其原始结构。这种模式通过创建一个包装对象来包裹真实组件,从而可以在运行时动态地增强对象的行为[^1]。 #### 实现方式 在JavaScript中实现装饰器通常涉及高阶函数的概念——即返回另一个函数的函数。下面是一个简单的例子展示如何利用闭包作为装饰器: ```javascript function loggingDecorator(wrappedFunction) { return function(...args) { console.log(`Calling ${wrappedFunction.name} with arguments`, args); const result = wrappedFunction.apply(this, args); console.log(`${wrappedFunction.name} returned `, result); return result; }; } // 应用装饰器到现有方法上 const originalMethod = (a, b) => a + b; const decoratedMethod = loggingDecorator(originalMethod); console.log(decoratedMethod(2, 3)); ``` 此代码片段展示了如何定义并应用`loggingDecorator`装饰器至`originalMethod`之上,使得每次调用该方法都会打印输入参数和输出结果的信息日志。 #### 场景实例 当涉及到实际项目中的具体应用场景时,装饰器可以用来做很多事情,比如权限验证、性能监控或是缓存优化等。这里给出两个典型的应用案例说明: ##### 权限控制 假设有一个API请求函数需要根据用户的登录状态决定是否发送网络请求,则可以通过如下所示的方式对其进行装饰: ```javascript function authRequired(apiCallFn) { return async (...params) => { if (!isUserLoggedIn()) { // 检查用户是否已登录 throw new Error('Unauthorized access'); } try { await apiCallFn(...params); // 如果授权成功则继续执行原逻辑 } catch(error){ handleError(error); // 处理错误情况下的异常捕获 } }; } ``` ##### 性能测量 为了跟踪某些昂贵的操作耗时多久完成,也可以编写相应的计时装饰器: ```javascript function timeIt(fn) { return function(...args) { let startTime = performance.now(); fn.apply(this, args); let endTime = performance.now(); console.info(`Execution took ${(endTime - startTime).toFixed(3)} ms`); }; } ``` 上述两种情况下都体现了装饰器模式的核心价值所在:无需修改被修饰的目标函数内部即可轻松附加新的行为特征[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值