javascript - 使用 JSON 解析/解析 js 对象时,返回方法中的函数范围会丢失

标签 javascript json function scope

我有一个有点疯狂的例子,但对于那些 JavaScript 函数作用域专家来说,它看起来是一个很好的练习:

(function (global) {
  // our module number one
  var body = function () {
    var someVar = 'some test text';
    return {
        method: function () {
            return someVar; // this will undefined when call this method in second module
        }
    };
  };
  var f = new Function([' return (', body, ')();'].join(''));
  global.r = f();
})(window);

(function (global) {
  // our module two
  var body = function () {
    // dep variable is injected on the fly with `new Function`
    dep.method(); // will throw `Reference Error: someVar is not defined`
  };

  // helper to propertly transform functions in JSON.stringify
  function transformFuncs (key, val) {
    if (typeof val === 'function') {
        return val.toString().replace(/(\t|\n|\r)/gm, '').replace(/("|')/gm, '\\"');
    }
    return val;
  }
  // injecting our first module inside
  var vars = ['var ', 'dep', ' = JSON.parse(\'', JSON.stringify(global.r, transformFuncs), '\', function (key, value) { if (value && typeof value === "string" && value.substr(0,8) == "function") { var startBody = value.indexOf("{") + 1; var endBody = value.lastIndexOf("}"); var startArgs = value.indexOf("(") + 1; var endArgs = value.indexOf(")"); return new Function(value.substring(startArgs, endArgs), value.substring(startBody, endBody)); } return value; });'].join('');
  // as variable
  var f2 = new Function([vars, ' return (', body, ')();'].join(''));
  global.r2 = f2();
})(window);

如果您在某个地方运行此代码,您会看到抛出异常 ReferenceError: someVar is not Defined

所以基本上这里发生了什么 - 我们创建一些模块,然后尝试将其作为变量注入(inject)另一个模块中。 JSON.parse 中用于正确获取字符串化函数的函数如下所示(如果您好奇的话):

function (key, value) { 
  if (value && typeof value === "string" && value.substr(0,8) == "function") { 
    var startBody = value.indexOf("{") + 1; 
    var endBody = value.lastIndexOf("}"); 
    var startArgs = value.indexOf("(") + 1; 
    var endArgs = value.indexOf(")"); 
    return new Function(value.substring(startArgs, endArgs), value.substring(startBody, endBody)); 
  } 
  return value; 
}

那么..问题是否有可能解决这种作用域行为?据我了解, global.r 在一个作用域中分配了 f 结果,但具有 method 函数的结果对象没有保存变量实例,因为 while为该函数创建 JSON 解析另一个作用域。

有什么想法吗?

P.S. 请不要问我为什么需要这个:) 只是考虑可能的解决方案。 主要思想是以某种方式注入(inject)第一个模块(查看顶部body var)作为第二个模块内的变量(body 第二个函数的 var)保存返回方法的原始范围

谢谢!

最佳答案

is it possible to workaround such scope behavior?

没有。作用域无法从外部访问,并且它们在函数序列化时必然会丢失。您只能对不引用任何自由变量的“纯”函数(如 body)进行字符串化。

这也是 JSON 格式不包含函数的原因。

The main idea is to somehow inject module number one as variable inside second module saving the original scope of methods that are returned.

插入引用,而不是字符串。依赖注入(inject)并不神奇,各种 JavaScript 模块加载器都可以做到这一点。

关于javascript - 使用 JSON 解析/解析 js 对象时,返回方法中的函数范围会丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25711565/

相关文章:

javascript - 等待每个进程完成

json - 将 "{}"主体解码为结构时,Golang 不会产生错误

c# - DefaultModelBinder 无法反序列化作为 JSON 对象传递给操作的 .NET Dictionary 对象?

c - 当一个函数被另一个函数调用时,它的技术术语是什么?

javascript - JavaScript 中的三种函数声明到底有什么区别?

python - 一个点和一组其他点之间的最短距离?

javascript - 如何在可折叠树的 d3.js 子级上添加点击事件?

javascript - 使用 jquery 比较 2 个输入

java - 如何解决使用@JsonTypeInfo时两次添加type属性的问题

javascript - POST 请求更改 url 并刷新页面