装饰器模式是一种设计模式,它可以在不改变一个对象本身的基础上,动态地给该对象添加一些新的功能。在JavaScript中,装饰器模式可以通过使用函数,对象和类结合起来使用实现。
1. 函数装饰器
函数装饰器是一种将一个函数包装在另一个函数中的技术。这个包装函数在调用原函数之前或之后执行一些逻辑,例如检查输入参数或修改函数返回值。在JavaScript中,可以通过创建一个函数来实现装饰器,然后将它应用到其他函数中。
下面是一个例子,展示了如何使用函数装饰器增强一个函数:
```
function withLogging(fn) {
return function() {
console.log('calling function:', fn.name);
const result = fn.apply(this, arguments);
console.log('result:', result);
return result;
}
}
function add(x,y) {
return x + y;
}
const enhancedAdd = withLogging(add);
console.log(enhancedAdd(2,3));
```
在这个例子中,我们定义了一个名为`withLogging`的函数装饰器。它接收一个函数作为参数,然后返回一个新的函数,用于调用原函数。这个新函数可以在原有逻辑上添加自定义逻辑,本例中就是在函数调用前后打印日志。通过将装饰器应用到原函数上,我们可以创建一个增强版函数`enhancedAdd`,并在调用它时看到日志输出。
2. 对象装饰器
对象装饰器是一种可以在对象上添加属性和方法的技术。在JavaScript中,我们可以使用ES6的标准语法,通过在一个对象的定义前使用`@`符号来应用一个或多个装饰器。
下面是一个例子,展示了如何使用对象装饰器增强一个对象:
```
function log(target) {
return class extends target {
hello() {
console.log('Hello, world!');
}
}
}
@log
class Person {
constructor(name) {
this.name = name;
}
}
const john = new Person('John');
john.hello();
```
在这个例子中,我们定义了一个名为`log`的对象装饰器。它接收一个对象作为参数,并返回以该对象为原型的新类。这个新类包含了自定义的方法`hello()`。我们使用`@log`装饰`Person`类,这样`Person`类将被增强为一个具有`hello()`方法的新类。在创建`john`实例时,我们可以调用`hello()`方法,并在控制台上看到输出。
3. 类装饰器
类装饰器是一种可以修改类的行为的技术。在JavaScript中,类装饰器是一个函数,它接收一个类作为参数,然后返回一个新的类或修改原有的类。
下面是一个例子,展示了如何使用类装饰器增强一个类:
```
function readonly(target, name, descriptor) {
descriptor.writable = false;
return descriptor;
}
class Person {
constructor(name) {
this.name = name;
}
@readonly
sayHello() {
console.log(`Hello, my name is ${this.name}.`);
}
}
const john = new Person('John');
john.sayHello();
john.sayHello = function() {
console.log('Sorry, I cannot say hello anymore.');
};
john.sayHello();
```
在这个例子中,我们定义了一个名为`readonly`的类装饰器。它接收三个参数,分别代表被装饰方法所属的类、方法名和属性描述符。在这里,我们将属性描述符的`writable`属性设置为`false`,这样被装饰方法就无法被修改了。
我们使用`@readonly`装饰`Person`类的`sayHello()`方法,这样这个方法就无法被修改了。在创建`john`实例后,我们调用`sayHello()`方法并看到输出。然后我们试图重新定义`sayHello()`,但是因为它被装饰成只读,所以失败了。
扫码咨询 领取资料