使用 JSON 对 js 对象进行分级/解析时,返回的方法中的函数作用域会丢失
Function scope is lost in returned methods when strigifying/parsing js objects with JSON
我有一个有点疯狂的例子,但对于那些精通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
异常。
所以基本上这里发生了什么 - 我们创建一些模块,然后尝试将其作为变量注入另一个模块中。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
函数的结果对象不会保存变量实例,因为在 JSON 解析时为该函数创建了另一个范围。
有什么想法吗?
附言请不要问我为什么需要这个:)想想可能的解决方案。主要思想是以某种方式将第一模块(查看顶部body
var(作为变量注入到第二个模块(第二个函数的body
变量(中,保存返回的方法的原始范围。
谢谢!
是否可以解决此类范围行为?
不。作用域无法从外部访问,并且在函数序列化时必然会丢失。您只能串化不引用任何自由变量的"纯"函数,例如body
。
这也是JSON格式不包含函数的原因。
主要思想是以某种方式将第一个模块作为变量注入到第二个模块中,保存返回的方法的原始范围。
注入引用,而不是字符串。依赖注入不是魔法,JavaScript 的各种模块加载器都可以做到。
相关文章:
- 从Javascript方法返回全局变量
- Meteor方法在客户端返回null,在客户端运行的相同方法返回正确的值
- AngularJS错误:提供程序必须从$get工厂方法返回值
- 修复AngularJS错误:提供程序必须从$get工厂方法返回值
- 从 javascript 中的对象方法返回一个对象
- 为什么我的Mongoose findAll方法返回500错误.
- 角度方法返回未绘制的代码
- 解析查询查找方法返回对象而不是数组
- Jquery Ajax调用没有't点击操作方法/返回整个HTML页面
- ajax方法返回错误时如何打印输出
- Meteor 方法返回客户端和服务器上的不同对象
- 如何将异步方法返回的值发送到javascript中的另一个异步方法
- Javascript getDay方法返回错误的数字
- Coffeescription类中的方法返回函数而不是字符串
- 当使用Q/promises/异步函数时,如何将一个值从一个类方法返回到另一个类
- find()方法返回具有不需要的属性的对象
- 如何在JSF中将toDataURL方法返回的画布内容作为图像存储在磁盘上
- 从请求.js请求方法返回结果
- jQuery的.children()方法返回'undefined'
- Angularjs 控制器在服务方法返回之前从服务中分配变量