HLJ 发布于
2025-06-11 10:11:57
0阅读

JavaScript 装饰器模式和转发:call/apply

JavaScript 装饰器模式和转发:call/apply

装饰器模式是一种结构型设计模式,它允许你通过将对象放入包含行为的特殊封装对象中来为原对象动态添加新的行为。在 JavaScript 中,我们可以使用函数转发和 call/apply 方法来实现这种模式。

装饰器模式基础

装饰器模式的核心思想是:不修改原有对象,而是通过包装(装饰)来扩展功能。

function doSomething() {
  console.log('Doing something');
}

// 装饰器函数
function decorator(func) {
  return function() {
    console.log('Before calling the original function');
    const result = func.apply(this, arguments);
    console.log('After calling the original function');
    return result;
  };
}

const decoratedDoSomething = decorator(doSomething);
decoratedDoSomething();

使用 call 和 apply 进行函数转发

callapply 是函数对象的方法,用于调用函数并指定 this 值:

function greet() {
  console.log(`Hello, ${this.name}`);
}

const person = { name: 'Alice' };

// 使用 call
greet.call(person); // Hello, Alice

// 使用 apply
greet.apply(person); // Hello, Alice

区别在于参数传递方式:

  • call 接受参数列表
  • apply 接受参数数组

实现装饰器模式

1. 缓存装饰器

function slow(x) {
  console.log(`Called with ${x}`);
  return x;
}

function cachingDecorator(func) {
  const cache = new Map();
  
  return function(x) {
    if (cache.has(x)) {
      return cache.get(x);
    }
    const result = func.call(this, x);
    cache.set(x, result);
    return result;
  };
}

slow = cachingDecorator(slow);
console.log(slow(1)); // 计算并缓存
console.log(slow(1)); // 从缓存获取

2. 方法装饰器 - 保持上下文

let worker = {
  someMethod() {
    return 1;
  },
  
  slow(x) {
    console.log(`Called with ${x}`);
    return x * this.someMethod();
  }
};

function cachingDecorator(func) {
  const cache = new Map();
  
  return function(x) {
    if (cache.has(x)) {
      return cache.get(x);
    }
    const result = func.call(this, x); // 保持正确的 this
    cache.set(x, result);
    return result;
  };
}

worker.slow = cachingDecorator(worker.slow);
console.log(worker.slow(2)); // 正常工作

3. 多参数装饰器

function hash() {
  return Array.from(arguments).join(',');
}

function cachingDecorator(func) {
  const cache = new Map();
  
  return function() {
    const key = hash(...arguments);
    if (cache.has(key)) {
      return cache.get(key);
    }
    const result = func.apply(this, arguments);
    cache.set(key, result);
    return result;
  };
}

现代 JavaScript 中的装饰器

ES6+ 引入了类装饰器语法(目前是 stage 3 提案):

@decorator
class MyClass {}

// 或
class MyClass {
  @decorator
  method() {}
}

实现示例:

function log(target, name, descriptor) {
  const original = descriptor.value;
  
  descriptor.value = function(...args) {
    console.log(`Calling ${name} with`, args);
    const result = original.apply(this, args);
    console.log(`Result: ${result}`);
    return result;
  };
  
  return descriptor;
}

class Calculator {
  @log
  add(a, b) {
    return a + b;
  }
}

const calc = new Calculator();
calc.add(2, 3); // 日志将被打印

总结

  1. 装饰器模式允许在不修改原始对象的情况下动态添加功能
  2. callapply 是实现装饰器的关键工具,用于正确转发调用
  3. 装饰器可以用于缓存、日志、验证等各种横切关注点
  4. 现代 JavaScript 提供了装饰器语法糖(需要 Babel 或 TypeScript 支持)

装饰器模式是 JavaScript 中非常强大的技术,特别适合实现 AOP(面向切面编程)风格的代码组织。

当前文章内容为原创转载请注明出处:http://www.good1230.com/detail/2025-06-11/810.html
最后生成于 2025-06-13 20:53:11
此内容有帮助 ?
0