使用不同的对象作为全局来评估字符串

时间:2013-09-12 18:15:16

标签: javascript eval global

有没有办法,使用纯javascript,做类似以下的事情?

var x = 12;
var subGlobal = {};
evalInGlobal(subGlobal, "x = 100;");

console.log(x); //--> 12
console.log(subGlobal.x); //--> 100

基本原理是我想在隔离的环境中运行脚本,因此每个脚本都可以引用xx不同(例如)。

3 个答案:

答案 0 :(得分:1)

我能得到的最近的是这个。它需要事先初始化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构建their parser以允许针对给定范围评估的表达式(JS的一小部分)的方式。

答案 1 :(得分:0)

我同意@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

答案 2 :(得分:0)

看来我要做的是通过使用esprima来解析代码来执行100%JavaScript方法,通过替换root 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]);
})

也就是说,它返回一个字符串,该字符串计算为一个函数,然后可以使用所选的全局对象调用该函数。它确实适当地确定范围等。有趣的东西。