装饰器函数属性

问题描述 投票:0回答:1

我试图从 https://javascript.info/call-apply-decorators

解决任务#1

事情是这样的:

创建一个装饰器间谍(func),它应该返回一个包装器,该包装器将所有对函数的调用保存在其调用属性中。

每个调用都保存为参数数组。

例如:

function work(a, b) {
  alert( a + b ); // 'work' is an arbitrary function or method
}

work = spy(work);

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

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

解决办法是:

function spy(func) {

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

  wrapper.calls = [];

  return wrapper;
}

在给定的解决方案(以及一般的闭包)中,我不明白的是分配给包装器的属性(wrapper.calls)现在也可用于“工作”功能。

使用

work = spy(work)
行,我们为“work”函数创建了包装器。现在后者的价值是

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

好的,“work”的值就是“wrapper”函数。并且“wrapper”具有 .calls 属性。但这个属性怎么也存在“工作”呢?

javascript closures decorator
1个回答
0
投票

弄清楚函数分配和闭包如何相互作用需要时间。尽我所能解释一下我的理解:

  1. 您将spy(work)的结果分配给work,因此work现在被spy返回的包装函数替换。在 JavaScript 中,函数是对象,因此这种替换本质上改变了 work 引用的内容。当您从间谍(工作)调用返回它时,它是包装函数。

  2. 在spy内部,创建了一个闭包,其中保存对原始工作函数func的引用。这允许包装函数在其本地范围内访问和调用原始函数。所以,基本上你最初创建的工作函数并没有被删除,你可以用不同的对象引用来指向它。

  3. 原来的work函数在闭包中保存为func,而work本身现在指向包装器。

  4. 通过将间谍的结果分配给工作,您可以有效地用从间谍返回的新对象(包装函数)替换工作。

  5. 新工作(现在是包装函数)保留对原始工作函数(在闭包中存储为 func )的访问。这允许包装器调用原始函数,同时跟踪其自己的属性(调用)。

  6. 本质上,将spy(work)分配给work意味着work现在指向包装函数,它具有原始函数之外的附加上下文和属性。

© www.soinside.com 2019 - 2024. All rights reserved.