0

闭包值在作为回调传递给由方法定义的另一个函数的函数中丢失。new Function()

代码

如何baz()修复函数以访问回调的闭包值

注意:该功能foo()不可修改。

const foo = () => {
  const b = 2;

  return (a) => {
    return a + b; // unable to access `b` here
  };
};

const bar = (a = 1, callback = foo()) => callback(a);

const baz = new Function(["a = 1", `callback = ${foo()}`], "return callback(a)");

console.log(bar(1)); // works fine and prints 3
console.log(baz(1)); // throws Uncaught ReferenceError: b is not defined

4

2 回答 2

1

不要将字符串插值与函数一起使用。在这里可以看到正在发生的事情:

const foo = () => {
  const b = 2;
  return (a) => a+b;
};
console.log(new Function(["a = 1", `callback = ${foo()}`], "return callback(a)"))

该函数(a) => a+b被转换为一个字符串,然后将其放入新函数的源代码中。是的,这会丢失闭包——它会丢失整个函数对象。

相反,只需写

const foo = () => {
  const b = 2;
  return (a) => a+b;
};
const bar = function(a = 1, callback = foo()) { return callback(a); };
const baz = new Function(["a = 1", "callback = foo()"], "return callback(a)");

console.log(bar(1));
console.log(baz(1));
console.log(bar);
console.log(baz);

正如您从记录的函数中看到的那样,它们的代码现在是等效的 - 由于演示片段中的所有内容都是全局的,因此它们的工作方式也相同。

foo(或您想从函数代码字符串访问的任何其他内容)在本地范围内定义时,情况会有所不同。在这种情况下,您需要使用这样的技巧来显式地使动态生成的代码可以使用该值。

于 2022-01-05T21:23:48.283 回答
-1

我相信 Function 构造函数只在全局范围内执行并且不创建闭包。这个答案可能会对您有所帮助:

函数构造 器 MDN

于 2022-01-05T20:32:57.380 回答