如何在一个范围内执行JS代码的不同部分

And*_*ewC 3 javascript scope

我有几个相互依赖的脚本块.我需要在一个范围内执行它们.

我的尝试:

var scopeWrapper = {}; 

with(scopeWrapper) {
    (function() {
        this.run = function(code) {
            eval(code);
        };
    }).call(scopeWrapper);
}

scopeWrapper.run('function test() { alert("passed"); }');
scopeWrapper.run('test();');
Run Code Online (Sandbox Code Playgroud)

我得到'测试未定义'错误.似乎代码在不同的范围内执行.为什么会这样?

Ben*_*aum 8

编辑: Bergi指出我原来的答案是错的,他是对的.由于eval在自己的范围内运行,并且函数构造函数仍然根据规范在函数范围内运行,因此这两者都不可能.

虽然我自己已经使用node.js多次使用vm模块来完成这类事情,在模块中您可以更好地控制代码执行的位置,但似乎浏览器需要不同的方法.

以这种方式共享变量的唯一方法是在JavaScript执行的全局范围内(可能在iframe中)这样做.您可以这样做的一种方法是脚本标记注入.

function run(code){
    var sc = document.createElement("script");
    sc.setAttribute("type","text/javascript");
    sc.innerHTML = code;
    document.body.appendChild(sc);
}

run("var x = 5");
run("document.write(x)");
Run Code Online (Sandbox Code Playgroud)

(这是代码在行动)

对于范围包装器,不是将它们注入同一帧中而是将它们注入另一个iframe.这会将他们的窗口对象范围限定为iframe,并允许您共享上下文.

我谦卑地为我之前的回答道歉,我误读了规范.我希望这个答案可以帮到你.

我在这里留下我之前的答案,因为我仍然认为它提供了一些有关如何evalFunction构造函数工作的见解.


在非严格模式下运行代码时,在eval页面的当前上下文中运行完成函数声明之后,声明它的作用域,以及函数.

考虑使用Function构造函数然后使用.call

在你的情况下,这将是:

var scopeWrapper = {}; 
scopeWrapper.run = function(code){
    var functionToRun = new Function(code);
    functionToRun.call(scopeWrapper);
}
scopeWrapper.run('this.test = function() { alert("passed"); }');
scopeWrapper.run("this.test()")
Run Code Online (Sandbox Code Playgroud)

以下是直接来自规范的参考:

如果没有调用上下文或者eval代码没有通过eval函数的直接调用(15.1.2.1.1)进行评估,则将执行上下文初始化为使用eval代码作为C的全局执行上下文如10.4.1.1中所述.

如果在node.js中运行此代码,请考虑使用vm模块.另请注意,这种方法在允许您运行的代码更改代码的方式上仍然不安全.

  • 我不认为`Function`构造函数可以帮助任何东西,函数的作用域也会死掉 - 它不适用于`run('function test(){alert("pass");}')`.你的作业代码也适用于`eval` (2认同)