有什么方法可以使用纯 javascript 来执行以下操作?
var x = 12;
var subGlobal = {};
evalInGlobal(subGlobal, "x = 100;");
console.log(x); //--> 12
console.log(subGlobal.x); //--> 100
理由是我想在隔离的环境中运行脚本,所以每个脚本都可以引用一个x
但有x
不同的(例如)。
有什么方法可以使用纯 javascript 来执行以下操作?
var x = 12;
var subGlobal = {};
evalInGlobal(subGlobal, "x = 100;");
console.log(x); //--> 12
console.log(subGlobal.x); //--> 100
理由是我想在隔离的环境中运行脚本,所以每个脚本都可以引用一个x
但有x
不同的(例如)。
我能得到的最接近的是这个。它需要预先初始化所global
使用的变量集。code
var evalInGlobal = function(global, code) {
global.x = null; // this is necessary
with(global) {
eval(code);
};
};
var x = 12;
var subGlobal = {};
evalInGlobal(subGlobal, "x = 100;");
console.log(x); //--> 12
console.log(subGlobal.x); //--> 100
为了摆脱初始化,我认为您必须将代码块转换为了解范围的东西。例如,通过调用转换x = 100;
并function(ctx) { ctx.x = 100; }
调用它fn(global)
。
这类似于 AngularJS 构建其解析器以允许针对给定范围评估表达式(JS 的一小部分)的方式。
我同意@LightStyle 上面的评论。然而,你可以做这样的事情,这可能不是你想要的。
var x = 12;
var subGlobal = function() {};
subGlobal.x = undefined;
function m() {
this.x = 100;
}
m.apply(subGlobal);
console.log(x); //--> 12
console.log(subGlobal.x); //--> 100
看来我要做的是通过使用esprima解析代码来执行 100% JavaScript 方法,通过将根 var 声明和未绑定变量分配替换为 的属性来修改解析树__thisglobal
,然后使用escodegen重新生成脚本并运行它。会看看情况如何。
编辑:它奏效了!现在它变成了这样的东西:
window.addSprite("Logo--oceanGamesLabel", Text("arial.ttf", [112, 112, 255], "Ocean Games"));
// ------------------- labels ----------------------
function labelText(text, halign) {
halign = halign || "right";
return Text("arial.ttf", [255, 255, 255], text,
halign, "center", "labels");
}
window.addSprite("Inputs--usernameLabel", labelText("Username: "));
window.addSprite("Inputs--passwordLabel", labelText("Password: "));
变成这样的东西:
/*-!-OGGlobalified-!-*/
(function ($$GLOBAL) {
return (function ($$GLOBAL) {
{
$$GLOBAL.TESTING = false;
}
$$GLOBAL.console.logf('login.init.js running on window %s(%s)', $$GLOBAL.window.name, $$GLOBAL.window.handle);
$$GLOBAL.window.addSprite('Logo--oceanGamesLabel', $$GLOBAL.Text('arial.ttf', [
112,
112,
255
], 'Ocean Games'));
{
$$GLOBAL.labelText = function (text, halign) {
$$GLOBAL.halign = $$GLOBAL.halign || 'right';
return $$GLOBAL.Text('arial.ttf', [
255,
255,
255
], $$GLOBAL.text, $$GLOBAL.halign, 'center', 'labels');
};
}
$$GLOBAL.window.addSprite('Inputs--usernameLabel', $$GLOBAL.labelText('Username: '));
$$GLOBAL.window.addSprite('Inputs--passwordLabel', $$GLOBAL.labelText('Password: '));
}).apply($$GLOBAL, [$$GLOBAL]);
})
也就是说,它返回一个字符串,该字符串评估为一个函数,然后可以使用选择的全局对象调用该函数。它确实正确地确定了范围等。好玩的东西。