2013-03-14 49 views
3

我有几个脚本块互相依赖。我需要在一个范围内执行它们。如何在一个范围内执行JS代码的不同部分

我尝试:

var scopeWrapper = {}; 

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

scopeWrapper.run('function test() { alert("passed"); }'); 
scopeWrapper.run('test();'); 

我得到 '测试没有定义' 的错误。看起来代码是在不同的作用域中执行的。 这是怎么回事?

+0

为什么你会这样做呢? – epascarello 2013-03-14 12:49:37

+1

@epascarello阅读代码,他正在制作一个脚本跑步者... – 2013-03-14 12:49:50

+0

@BenjaminGruenbaum,我知道,我想知道*为什么*,而不是它做什么。 – epascarello 2013-03-14 13:00:36

回答

8

编辑:Bergi指出我原来的答案是错的,他是对的。由于eval在其自己的作用域中运行,并且功能构造函数仍然按照spec在功能范围内运行,所以这两个都不可行。

虽然我自己使用vm模块多次使用node.js完成了这类事情,您可以对代码的执行位置进行更细致的控制,但似乎浏览器需要不同的方法。

以这种方式共享变量的唯一方法是在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)"); 

here is this code in action

至于范围包装,在另一iframe,而不是在相同的帧注入它们注入它们。这会将其窗口对象的范围限制在该iframe中,并允许您共享上下文。

我对以前的回答谦虚道歉,我误读了规范。我希望这个答案能帮助你。

我在这里留下我以前的答案,因为我仍然相信它提供了一些有关evalFunction构造函数如何工作的信息。


当您 页面的当前上下文的函数声明后运行在非严格模式eval运行的代码完成,范围就被宣布死亡中,与它的功能。

考虑使用Function constructor然后.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()") 

这里是一个参考直接from the spec:

如果没有呼叫上下文或如果eval代码没有通过直接调用(15.1.2.1.1)评估eval函数,那么 Init如10.4.1.1所述,使用eval代码作为C来对执行上下文进行ialize,就好像它是一个全局执行上下文一样。

如果此代码在node.js中运行,请考虑使用vm模块。还要注意,这种方法仍然不安全,它将允许您运行代码来更改代码。

+1

我喜欢这个想法(+1),但它认为值得注意的是,真正的“scopeWrapper”正在执行共享*上下文*中的所有内容,而不是共享范围*。请注意,如果将'this.test = func ...'替换为'var test = func ...',它将不起作用(不同于它的范围相同)。 – 2013-03-14 13:20:51

+0

你绝对正确,谢谢。 – 2013-03-14 13:34:33

+2

我不认为'Function'构造函数有什么帮助,函数的作用域也会死掉 - 它不会与'run('function test(){alert(“passed”);}')'一起工作。您的分配代码也可以与'eval'配合使用 – Bergi 2013-03-14 14:01:19

0

test只存在于的this.run范围和仅在通话时间:

// global scope 
(function(){ 
    // local scope (equivalent of your "run" function scope) 
    eval('function f(){};'); 
    console.log(f); // prints "function f(){}" 
})(); 
console.log(f); // prints "ReferenceError: f is not defined" 

run每个呼叫创建了一个新的范围,其中每个code单独评估。

+0

他正在设置this.run。另外,问题出在_eval_上下文决定的方式(请参阅我的答案),而不是定义_run_的范围...... – 2013-03-14 12:55:25

+0

我的意思是“this.run'内部”。 – leaf 2013-03-14 12:58:39

相关问题