前端装饰器

本文介绍了JavaScript中的装饰器,一种用于在类和类属性间共享和扩展功能的机制。装饰器分为类装饰器、属性装饰器和函数装饰器,它们分别用于类、类属性和函数的增强。通过示例展示了如何使用装饰器添加额外的行为,如设置属性为只读。装饰器使代码更加简洁、可重用,并降低了复杂性,便于维护。

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

今天和公司同事去做核酸的路上闲聊,便聊到了刚才他面试问新员工的一个问题:装饰器。我对它算是比较陌生的。之前也没有接触过,在我从它的字面意思的理解上认为:“它可能是一层对方法的装饰,就和Vue中的路由钩子差不多,在跳转路由前走一遍,做一些判断的逻辑操作之类的”。然后同事给我劈里啪啦一顿讲,我也听的懵懵的。回去后仔细看了,简单的介绍下装饰器


简介

pythod之类的语言中装饰器很早就出现了,而对JavaScript中的装饰器的支持仍处于第 2 阶段提案中,我们需要使用babel将代码转为ES5或者ES6才可以使用。
当我们需要在多个不同的类之间共享或者扩展一些方法或行为的时候,代码会变得错综复杂,极其不优雅,这也就是装饰器被提出的一个很重要的原因。

Javascript 中的装饰器

总的来说,我们可以在 JavaScript 中分出 3 种类型的装饰器:

类装饰器—— 一次应用于整个类。

类成员装饰器(属性装饰器)——应用于类的成员

函数装饰器——用函数来包装函数。

装饰器的具体表现

  • 类装饰器只接收一个参数类本身
function add(target){
	 target.prototype.age = 22
}
@add(50)
class person {
    name = ''
    constructor(name) {
        this.name = name
    }
}
const stu = new person('Tom')
console.log(stu.name)	// Tom
console.log(stu.age)	// 22
  • 属性装饰器接收三个参数
    1、target - 成员所在的类。
    2、name - 类成员的名称。
    3、descriptor - 成员描述符。
function readonly(target, name , descriptor){
    descriptor.writable = false
}
class person {
    @readonly
    sub(){
        console.log('我是sub')
    }
}
const stu = new person('dw')
stu.sub = ()=>{
    console.log('ads')
}
stu.sub()	// TypeError: Cannot assign to read only property 'sub' of object '#<person>'
  • 函数装饰器
    函数是不能使用直接使用装饰器,因为函数存在函数提升的特性。但是我们可以使用高阶函数来实现装饰器 的功能。
function multiply(x, y) {
    console.log('total : ' + (x * y));
}
function logDecorator(logger) {
    return function () {
        return logger.apply(this, arguments);
    }
}
const wrapperFunction = logDecorator(multiply);
wrapperFunction(10,10)

总结

装饰器引入 JavaScript 的主要目的是在 JavaScript 类和类属性之间共享功能。
但是,这并不是装饰器带来的唯一优势。
装饰器允许开发人员编写干净且可重用的代码。开发人员可以使用装饰器轻松地将功能的增强与代的码特性分开。
除此之外,装饰器语法非常简单,允许在不增加代码复杂性的情况下向类和属性添加新功能。
这使得代码更易于维护和调试。

### 前端 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、付费专栏及课程。

余额充值