我试图将一个函数 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
在这里做什么以及为什么这种方式有效? 最佳答案
这两个功能的工作方式不同。您的装饰器在传递的函数上定义 calls
属性。另一个装饰器函数在嵌套和返回 ( wrapper
) 函数上设置属性。您会收到该错误,因为 work.calls
是 undefined
。装饰的 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 __;
}
关于JavaScript:TypeError:work.calls 在函数装饰器中不可迭代(初学者问题),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52531907/