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

Is it possible to use closure scope of a function that receives data as a argument?

有一个函数需要一个接收数据参数的回调函数。我需要一种在回调中访问 foo 的方法。通过阅读,我发现闭包范围可以是解决方案,但是我一直在努力寻找一个示例,其中回调也接收数据对象(或与此相关的任何变量)。

 const foo = 1;


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

       return bar;
  })

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

您当前的代码 是正确的 因为 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".