提问人:Vinay Sharma 提问时间:1/6/2022 更新时间:1/6/2022 访问量:182
JavaScript 函数闭包值丢失
JavaScript function closure value lost
问:
闭包值在作为回调传递给方法定义的另一个函数的函数中丢失。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
答:
-1赞
BCollingwood
1/6/2022
#1
我相信函数构造函数仅在全局范围内执行,并且不创建闭包。这个答案可能会对你有所帮助:
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
那么,你的开发环境是什么?那里有全局变量吗?为什么它说 ,代码不使用?foo
eval
0赞
Vinay Sharma
1/7/2022
我的开发环境是一个编码测试平台。不,那里不是全局变量,因为该文件除了您的解决方案之外什么都没有。它说可能是因为编译器与此语法不兼容,或者它正在尝试评估我的代码。好吧,该平台也针对一些测试用例运行了一些 Mocha 测试,但它们似乎不会抛出错误,因为它们甚至没有运行,因为代码在编译时错误失败。如果您觉得此错误无法在您的解决方案下解决,我仍然可以接受您的答案,因为它似乎在正常的开发环境中工作正常。foo
eval
0赞
Bergi
1/7/2022
如果它不是全局的,则构造者看不到它 - 尝试我链接的方法。但这听起来不像是编译时错误,如果您需要有关该平台的进一步帮助,请提出一个新问题。Function
const baz = new Function("{foo}", "return function(a = 1, callback = foo()) { return callback(a); };")({foo})
ReferenceError
评论