Javascript 如何从堆栈顶部执行JS函数?

Javascript 如何从堆栈顶部执行JS函数?,javascript,Javascript,我想从堆栈顶部执行一个函数。也就是说,任何用“var”定义的变量都应该在全局意义上定义。这可能吗?fn.呼叫(窗口)不工作 <script> var foo = "I am top level foo."; var fn = function(){ var foo = "Setting foo from in a function"; } fn.call(window); //doesn't work, var is still set locally

我想从堆栈顶部执行一个函数。也就是说,任何用“var”定义的变量都应该在全局意义上定义。这可能吗?fn.呼叫(窗口)不工作

<script>
  var foo = "I am top level foo.";

  var fn = function(){
    var foo = "Setting foo from in a function";
  }

  fn.call(window);  //doesn't work, var is still set locally in fn.
  alert(foo);  //desired effect will alert "setting foo from in a function"
</script>

var foo=“我是顶级foo。”;
var fn=函数(){
var foo=“在函数中设置foo from”;
}
fn.呼叫(窗口)//不起作用,var仍在fn中本地设置。
警报(foo)//所需效果将提示“在函数中设置foo”
请注意:我完全知道,不指定“var”会使项目成为全局变量。问题是我无法指定“fn”的内容,它是用户定义的,但预期将从顶层运行


如果有必要,我愿意使用eval。

你的问题问得太多了。局部变量就是:局部变量。它们是在函数的本地作用域中创建的,不会导出到调用之外。作为调用者,您根本看不到它们,因为它们没有存储在您可以访问的任何类型的散列、名称空间或对象中

最好的办法是让用户修改其功能

我想,如果不这样做,您可以跳过火环,对函数的
toSource()
源代码执行一些字符串搜索和替换,并删除
var
关键字。或者使用
toSource()
,删除
函数{
..
}
包装,然后
eval()
删除该代码。那可能行得通。但这是一个过多的磨蹭,非常脆弱,主要的代码气味


如果您可以修改函数,那么解决方案很简单。如果去掉
var
,则将修改全局变量。
var
的目的是专门创建局部变量,所以不要使用它,你就在那里了

var fn = function() {
    foo = "Setting foo from in a function";
}
如果要显式影响全局范围,请修改作为全局对象容器的
窗口
对象:

var fn = function() {
    window.foo = "Setting foo from in a function";
}

我不确定你想做什么,但你不能用那种方式覆盖
foo
的值。在全局上下文中指定
var foo
时,它将附加到全局对象(在全局范围内)

然后,当您在函数中指定
var foo
时,您在该函数的范围内声明了它。这意味着外界对它一无所知+。你能做的就是这样:

var fn = function() {
   this.foo = "Setting foo from in a function";
};
或者更明确地说:

var fn = function() {
  window.foo = "Setting foo from in a function";
};
这是你想要的吗

+在函数中定义
foo
时,它附加到激活对象,而不是全局对象。每次输入函数的执行上下文时,都会创建一个新的激活对象。因此,每次调用该函数时,都会得到一个新的
foo
。这也是一样,否则您将无法创建函数范围内的局部变量;它们将渗透到全球环境中

更新

如果您真的想在全局上下文中计算函数内部的代码,我想您可以执行如下操作。这很难看,我不知道你为什么要这么做,但这里有:

var foo = 2;

var fn = function() {
   var foo = 3;
}

console.log(foo); //prints 2

var fnSource = fn.toSource();
eval(fnSource.replace(/^\(function\s*\(\)\s*{/, "").replace(/}\s*\)$/, ""));

console.log(foo); //prints 3

这将删去<代码>(函数)({ /代码>和<代码> })<代码>,以便只在中间结束代码,然后运行<代码> EVA


再次强调,我不建议这样做。

不要使用
var
,而是在
this
对象内设置变量。这样,如果使用
窗口调用函数
,将设置“全局”变量:

window.foo = "I am top level foo.";

var fn = function(){
    this.foo = "Setting foo from in a function";
}

fn.call(window);
alert(foo);
然后还可以使用不同的上下文调用函数:

var anObject = { foo: "Initial Value" };
fn.call(anObject);
alert(anObject.foo); // Will be the modified value

您可以在不更改
fn
的情况下获得此效果,但此代码不适用于心脏虚弱者:

<script type="text/javascript">
var gFoo = "";

var fn = function() {
    var foo = "Setting foo from in a function";
}

var fnText = fn.toString();
var newFunction = fnText.substring(0, fnText.length - 1) + "gFoo = foo; }";

eval("var x = " + newFunction + "; x();");
alert(gFoo);
</script>

var gFoo=“”;
var fn=函数(){
var foo=“在函数中设置foo from”;
}
var fnText=fn.toString();
var newFunction=fnText.substring(0,fnText.length-1)+“gFoo=foo;}”;
eval(“var x=“+newFunction+”;x();”;
警报(gFoo);

您是说希望在不更改
fn的实现的情况下获得此效果?您希望
fn
声明一个新的局部变量,并以某种方式覆盖全局声明的
foo
?我不明白你在问什么。三个答案都被删除了,因为他们没有阅读整个问题-D也许你应该突出最后一段重要的内容。@John:那是不正确的。这是在原来的问题中。对你正在努力实现的目标有更多的了解将有助于引导答案朝着正确的方向发展。@Ian:完全正确。我希望fn被执行,就像它是顶级代码的一部分一样。或者,换句话说,我想评估fn的内容。我知道scope是如何工作的,我相信你理解了我的意图。只是想确定一下:你是说绝对没有办法在全局空间中执行函数吗?你是在尝试在全局上下文中计算函数内部的代码吗?@Vivin:这正是我想说的do@Sambo:我已经更新了我的解决方案。它应该做你想做的事情,尽管听起来很疯狂:)@Sambo没问题。但正如我已经提到的,这在许多不同层面上都是一场维护噩梦。它也可能是各种潜在错误的来源,而且它非常不易维护和脆弱。你已经被警告了!:)如问题所述,我不能更改fn的内容。这包括更改任何变量实例化。toSource()?现在我们发现了一些事情!我不能直接eval()到source吗?@Sambo当然可以——看看我的解决方案。