5个JavaScript装饰器实用技巧:参数校验、属性保护与调用拦截
本文深入解析JavaScript装饰器的五个核心应用场景。通过具体代码示例,演示如何利用装饰器实现函数参数的类型校验与默认值设置、类属性的访问保护与初始化、返回值的类型检查与格式化,以及函数调用前后的前置与后置逻辑拦截。掌握这些技巧有助于编写更健壮、易维护的JavaScript代码。
装饰器
什么是装饰器
装饰器本质上是一个函数,它接收一个函数或类作为输入参数,并返回经过修改后的函数或类。在代码中,可以通过 @ 符号将装饰器应用于目标函数或类定义。
下面是一个简单的装饰器示例:
function myDecorator(target) {
// 对类或函数进行修改
return target;
}
@myDecorator
class MyClass {
// 类的定义
}
@myDecorator
function myFunction() {
// 函数的定义
}装饰器的作用
装饰器可以应用于多种开发场景,例如:
- 类属性保护
- 函数参数类型检查
- 函数返回值类型检查
- 函数调用计时
本文将详细介绍如何利用装饰器处理函数参数、类属性、函数返回值以及函数调用过程,通过具体案例展示其实际应用。
装饰函数参数
参数类型检查
利用装饰器可以实现对函数参数类型的严格检查。以下示例展示了如何使用装饰器验证传入参数的类型:
function myParameterDecorator(target, name, descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
args.forEach((arg, index) => {
const argType = typeof arg;
if (argType !== 'number' && argType !== 'string') {
throw new Error(`Argument ${index} is of type ${argType}, but should be a string or a number`);
}
});
return originalMethod.apply(this, args);
}
return descriptor;
}
class MyClass {
@myParameterDecorator
myMethod(name, age) {
console.log(`Hello, my name is ${name} and I am ${age} years old`);
}
}
const myObject = new MyClass();
myObject.myMethod("Alice", 30); // 输出:Hello, my name is Alice and I am 30 years old
myObject.myMethod("Bob", "thirty"); // 抛出错误:Argument 1 is of type string, but should be a string or a number在上述示例中,@myParameterDecorator 装饰器会在 myMethod 函数执行前,遍历检查所有传入参数是否为字符串或数字类型。若参数类型不符合要求,系统将抛出错误提示。
参数默认值
除了类型检查,装饰器还可用于设定函数参数的默认值。以下示例演示了如何为参数设置默认值:
function myParameterDecorator(target, name, descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(name = "World") {
return originalMethod.call(this, name);
}
return descriptor;
}
class MyClass {
@myParameterDecorator
myMethod(name) {
console.log(`Hello, ${name}`);
}
}
const myObject = new MyClass();
myObject.myMethod(); // 输出:Hello, World
myObject.myMethod("Alice"); // 输出:Hello, Alice在上述示例中,@myParameterDecorator 装饰器会检查 myMethod 调用时是否传入了 name 参数。若未传入,则自动使用默认值 "World" 进行后续处理。
装饰类属性
类属性保护
通过装饰器可以有效保护类属性,防止其被意外修改或直接访问。以下示例展示了如何保护类属性:
function myPropertyDecorator(target, name) {
let value = target[name];
const getter = function() {
return value;
};
const setter = function(newValue) {
if (typeof newValue === 'string') {
value = newValue;
} else {
throw new Error(`Property ${name} must be a string`);
}
};
delete target[name];
Object.defineProperty(target, name, {
get: getter,
set: setter,
enumerable: true,
configurable: true,
});
}
class MyClass {
@myPropertyDecorator
myProperty = "initial value";
}
const myObject = new MyClass();
console.log(myObject.myProperty); // 输出:initial value
myObject.myProperty = "new value";
console.log(myObject.myProperty); // 输出:new value
myObject.myProperty = 123;
// 抛出错误:Property myProperty must be a string在上述示例中,@myPropertyDecorator 装饰器用于保护 MyClass 类的 myProperty 属性。若尝试将该属性赋值为非字符串类型,系统将抛出错误以阻止非法赋值。
类属性初始值
装饰器同样可用于设定类属性的初始值。以下示例展示了如何为属性设置默认初始值:
function myDefaultDecorator(defaultValue) {
return function(target, name) {
target[name] = defaultValue;
}
}
class MyClass {
@myDefaultDecorator('initial value')
myProperty;
}
const myObject = new MyClass();
console.log(myObject.myProperty); // 输出:initial value在上述示例中,@myDefaultDecorator 装饰器用于为 MyClass 类的 myProperty 属性设定初始值为 "initial value",确保实例化时拥有确定的初始状态。
装饰函数返回值
返回类型检查
利用装饰器可以验证函数返回值的类型。以下示例展示了如何检查返回值类型:
function myReturnDecorator(target, name, descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
const result = originalMethod.apply(this, args);
if (typeof result !== 'number') {
throw new Error(`Method ${name} must return a number`);
}
return result;
}
return descriptor;
}
class MyClass {
@myReturnDecorator
myMethod() {
return 42;
}
}
const myObject = new MyClass();
console.log(myObject.myMethod()); // 输出:42
myObject.myMethod = function() {
return "not a number";
};
// 抛出错误:Method myMethod must return a number在上述示例中,@myReturnDecorator 装饰器会在 myMethod 函数执行后,检查其返回值是否为数字类型。若返回值类型不符,系统将抛出错误。
返回值格式化
装饰器还可用于对函数返回值进行格式化处理后返回。以下示例展示了如何格式化返回值:
function myFormatDecorator(target, name, descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
const result = originalMethod.apply(this, args);
if (typeof result === 'string') {
return result.toUpperCase();
} else {
return result;
}
}
return descriptor;
}
class MyClass {
@myFormatDecorator
myMethod() {
return "hello, world";
}
}
const myObject = new MyClass();
console.log(myObject.myMethod()); // 输出:HELLO, WORLD在上述示例中,@myFormatDecorator 装饰器会将 myMethod 函数的返回值统一转换为大写字母格式后再返回。
装饰函数调用
前置操作
利用装饰器可以在函数正式调用前执行特定的前置操作。以下示例展示了如何在调用前执行操作:
function myBeforeDecorator(before) {
return function(target, name, descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
before();
return originalMethod.apply(this, args);
}
return descriptor;
}
}
class MyClass {
@myBeforeDecorator(() => console.log("before"))
myMethod() {
console.log("myMethod");
}
}
const myObject = new MyClass();
myObject.myMethod();
// 输出:
// before
// myMethod在上述示例中,@myBeforeDecorator 装饰器会在 myMethod 函数执行前,先调用一个预定义的回调函数。
后置操作
装饰器同样可用于在函数调用结束后执行特定的后置操作。以下示例展示了如何在调用后执行操作:
function myAfterDecorator(after) {
return function(target, name, descriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args) {
const result = originalMethod.apply(this, args);
after(result);
return result;
}
return descriptor;
}
}
class MyClass {
@myAfterDecorator(result => console.log("after: " + result))
myMethod() {
console.log("myMethod");
return "result";
}
}
const myObject = new MyClass();
console.log(myObject.myMethod());
// 输出:
// myMethod
// after: result
// result在上述示例中,@myAfterDecorator 装饰器会在 myMethod 函数执行后,调用一个回调函数,并将原函数的返回值作为参数传递给该回调函数。
总结
本文介绍了五个使用 JavaScript 装饰器的技巧,包括装饰函数参数、装饰类属性、装饰函数返回值和装饰函数调用,这5个不同的JavaScript装饰器技巧,这些技巧可以让你的代码更加美观、优雅和易于阅读,还可以帮助我们更好地组织代码和增强扩展函数和类的功能。
以上就是5个让你眼前一亮的JavaScript装饰器技巧的详细内容,更多关于JavaScript装饰器技巧的资料请关注本站其它相关文章!
JavaScript闭包与类(Class)的区别及适用场景对比
2026-11-05 15:48:57
JavaScript入门要学ES6吗?let与箭头函数等新特性解析
2026-11-05 14:49:16
JavaScript 8种数据类型详解:基本类型与引用类型的区别
2026-11-05 14:25:15
怎么在JavaScript中使用async/await优化Ajax异步流程
2026-11-05 13:56:15
JavaScript replace回调函数实现动态正则替换逻辑
2026-11-05 13:52:13
