我有一些疯狂的例子,但对于那些专业的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解析。 / p>
有什么想法吗?
P.S。请不要问为什么我需要这个:)只考虑可能的解决方案。 主要思想是以某种方式注入第一个模块(查看顶部body
var)作为第二个模块中的变量(第二个函数的body
var) 保存返回的方法的原始范围。
谢谢!
答案 0 :(得分:1)
是否可以解决此类范围行为?
没有。范围从外部无法访问,并且在函数序列化时必然会丢失。你只能字符串化#34; pure"像body
这样的函数不引用任何自由变量。
这也是JSON格式不包含函数的原因。
主要思想是以某种方式将第一模块作为变量注入第二个模块中,从而保存返回的方法的原始范围。
注入引用,而不是字符串。依赖注入并不神奇,JavaScript的各种模块加载器都可以做到。