【问题标题】:JavaScript: TypeError: work.calls is not iterable in function decorator (beginner question)JavaScript:TypeError:work.calls 在函数装饰器中不可迭代(初学者问题)
【发布时间】:2018-09-27 07:43:34
【问题描述】:

我试图将函数 work 传递到装饰器中,它将函数调用保存在数组 work.calls 中。

功能:

work(a, b) {
  console.log(a + b);
}

装饰者:

function decorator(func) {
  func.calls = [];
  return function(...args) {
    func.calls.push(args);
    return func.call(this, ...args);
  }
}

装饰函数work:

work = decorator(work);

调用新函数:

work(1, 2); // 3
work(4, 5); // 9

for (let args of work.calls) {
  console.log( 'call:' + args.join() ); // TypeError: work.calls is not iterable
}

work.calls 是一个数组,为什么不能迭代?

作为参考,还有另一个由其他人编写的实际工作的装饰器版本:

function decorator(func) {

  function wrapper(...args) {
    wrapper.calls.push(args);
    return func.apply(this, arguments);
  }

  wrapper.calls = [];

  return wrapper;
}

work(1, 2); // 3
work(4, 5); // 9

for (let args of work.calls) {
  alert( 'call:' + args.join() ); // "call:1,2", "call:4,5"
}

wrapper 在这里做什么以及为什么这种方式有效?

【问题讨论】:

    标签: javascript decorator typeerror


    【解决方案1】:

    这两个功能的工作方式不同。您的装饰器在传递的函数上定义了 calls 属性。另一个装饰器函数设置嵌套和返回 (wrapper) 函数的属性。你会得到那个错误,因为work.callsundefined。装饰的work 指的是匿名函数:return function(...args),它没有calls 属性。

    如果将work = decorator(work); 更改为let work2 = decorator(work);,您将看到calls 设置在原始work 函数上,而不是work2

    如果您在闭包的返回函数上定义 calls 属性,则您的代码的工作方式相同。

    function decorator(func) {
      function __(a, b) {
        __.calls.push([a, b])
        return func(a, b)
      }
      __.calls = []
      return __;
    }
    

    【讨论】:

      猜你喜欢
      • 2022-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多