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

标签: javascript closures


【解决方案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"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-01
    • 1970-01-01
    相关资源
    最近更新 更多