是否可以使用接收数据作为参数的函数的闭包范围?

Posted

技术标签:

【中文标题】是否可以使用接收数据作为参数的函数的闭包范围?【英文标题】:Is it possible to use closure scope of a function that receives data as a argument? 【发布时间】:2022-01-08 07:45:30 【问题描述】:

有一个函数需要一个接收数据参数的回调函数。我需要一种在回调中访问 foo 的方法。从阅读中我发现闭包范围可以成为解决方案,但是我很难找到一个回调也接收数据对象(或任何变量)的示例。

 const foo = 1;


 this.editor.functionThatExpectsCallback('genericString', (data) => 
       // do stuff with foo here, e.g.
       const bar = foo + data.num;      

       return bar;
  )

基本上问题是 foo 在回调范围内未定义,我需要定义它,同时仍保持对数据的访问。我非常感谢我能在这里得到的任何帮助。如果您需要更多信息,我很乐意提供。

【问题讨论】:

"基本上问题是 foo 在回调范围内未定义" 那么您的代码不会证明这一点,因为它用你有代码。 好吧,为了这篇文章,我简化了我的代码,但我没有访问权限。你确定总是这样吗? Yes, I am 我相信回调函数是在不同的服务中远程执行的。这可能是 foo 未定义的原因吗? 首先,您可能必须检查所调用内容的文档——它可能会为此提供一种机制。如果没有,那么很遗憾,您将不得不从new Function("data", `const bar = $foo + data.num; return bar;`) 之类的字符串生成函数,但您必须非常小心,不要碰巧产生无效代码。 【参考方案1】:

您当前的代码是正确的,因为that is how scopes work - 任何来自外部范围的内容都可以在内部范围内看到。

它不起作用的唯一原因是函数被序列化然后反序列化 - 这完全删除了所有范围信息:

 //different scope here
  const foo = 1;
  const result = functionThatExpectsCallback('genericString', (data) => 
    // do stuff with foo here, e.g.
    console.log("foo is:", typeof foo);
    const bar = foo + data.num;

    return bar;
  );
  
  console.log(result);


//dummy implementation that serialises and deserialises a function to run it:

function functionThatExpectsCallback(arg, callback) 
  return runFromString(callback.toString());


function runFromString(strFunc) 
  const fn = eval(`($strFunc)`);

  return fn( num: 2 );

解决这个问题的第一种方法是检查使用的任何库的文档 - 它可能提供一种发送额外参数的方法。

如果这不是一个选项,那么您需要以肮脏的方式进行操作并从字符串生成函数。你可以使用the Function constructor 来做到这一点

 //different scope here
  const foo = 1;
  
  const generatedFunction = new Function("data", `
    // do stuff with foo here, e.g.
    const bar = $foo + data.num;

    return bar;
  `);
  
  const result = functionThatExpectsCallback('genericString', generatedFunction);
  
  console.log(result);


function functionThatExpectsCallback(arg, callback) 
  return runFromString(callback.toString());


function runFromString(strFunc) 
  const fn = eval(`($strFunc)`);

  return fn( num: 41 );

您必须非常小心,因为从字符串生成函数时很容易引入小错误,并且最终可能会出现无效代码。例如,如果foo 是字符串foo = "hello",则生成的代码将是const bar = hello + data.num;,这是无效的,因为hello 将是一个从未定义的变量,而不是字符串文字"hello"

【讨论】:

以上是关于是否可以使用接收数据作为参数的函数的闭包范围?的主要内容,如果未能解决你的问题,请参考以下文章

Python基础:19.函数式编程:高阶函数返回函数闭包偏函数

装饰器

Groovy闭包 Closure ( 闭包作为函数参数 | 代码示例 )

Groovy闭包 Closure ( 闭包作为函数参数 | 代码示例 )

函数与参数,闭包

带有不匹配参数的闭包调用:函数'_RegisterState.build.<匿名闭包>'接收者:闭包:(字符串)=> Null