JavaScript 函数闭包值丢失

JavaScript function closure value lost

提问人:Vinay Sharma 提问时间:1/6/2022 更新时间:1/6/2022 访问量:182

问:

闭包值在作为回调传递给方法定义的另一个函数的函数中丢失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

JavaScript 函数 调闭包 uncaught-reference-error

评论


答:

-1赞 BCollingwood 1/6/2022 #1

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

函数构造函数 MDN

1赞 Bergi 1/6/2022 #2

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

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

评论

0赞 Vinay Sharma 1/7/2022
好吧,它似乎在这里工作,但在我的开发环境中不起作用。代码不编译并抛出ReferenceError: foo is not defined at eval
0赞 Bergi 1/7/2022
那么,你的开发环境是什么?那里有全局变量吗?为什么它说 ,代码不使用?fooeval
0赞 Vinay Sharma 1/7/2022
我的开发环境是一个编码测试平台。不,那里不是全局变量,因为该文件除了您的解决方案之外什么都没有。它说可能是因为编译器与此语法不兼容,或者它正在尝试评估我的代码。好吧,该平台也针对一些测试用例运行了一些 Mocha 测试,但它们似乎不会抛出错误,因为它们甚至没有运行,因为代码在编译时错误失败。如果您觉得此错误无法在您的解决方案下解决,我仍然可以接受您的答案,因为它似乎在正常的开发环境中工作正常。fooeval
0赞 Bergi 1/7/2022
如果它不是全局的,则构造者看不到它 - 尝试我链接的方法。但这听起来不像是编译时错误,如果您需要有关该平台的进一步帮助,请提出一个新问题。Functionconst baz = new Function("{foo}", "return function(a = 1, callback = foo()) { return callback(a); };")({foo})ReferenceError