JavaScript 函数闭包值丢失

JavaScript function closure value lost

Closure 值在函数中得到 lost 作为 callback 传递给定义的另一个函数通过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

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

MDN

不要对函数使用字符串插值。可以在这里看到发生了什么:

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(或您希望从函数代码字符串访问的任何其他内容)定义在本地范围内时,情况会有所不同。在这种情况下,您需要使用 trick like this 来显式地使该值可用于动态生成的代码。