在另一个作用域内运行函数

4

我试图避免在if语句中有非常长的代码块,所以我想将另一个函数调用到当前范围内:

var f = function(){ alert(a); };

(function(){
    var a = "abc.";
    f(); //undefined
    eval("("+f+")()"); //this works, but eval is evil
})();

我可能对作用域的基础知识或其他更好的方法缺乏理解,所以无法弄清楚是什么问题。有没有想法如何解决这个问题?我不想通过函数参数传递所需的变量。
提前感谢!
3个回答

1

您需要确保将您想要警报的变量传递给函数。

var f = function(a){ alert(a); };

(function(){
    var a = "abc.";
    f(a); //passing it the reference to a
})();

编辑:如果你真的不想传递一个变量,那么你需要首先在全局范围内设置a。当在函数内使用var时,你创建的是一个只在该函数中可用的局部变量。去掉var,这样你就能更新全局版本的变量。

var f = function(){ alert(a); };
var a = ""; // declare a in global scope

(function(){
    a = "abc."; // dont use var, we just update the global scope.
    f(); // F runs and grabs a from global scope
})();

抱歉,在问题中没有说清楚,但我不想将它作为参数传递。 - mattsven
1
我更新了我的回答,但请不要这样做,一旦你的代码变得更复杂,这会带来很多麻烦。 - wesbos
@Wes,只是提醒一下- 你的 var a = ""; 是多余的。你可以把它去掉,得到相同的结果。你最初声明的 a(带有关于它在全局范围内的注释)引用的对象与稍后设置值的 a 引用的对象不同。 - evan
1
你是对的,完全省略 var 会将它扔进全局作用域,但这是非常糟糕的做法。始终在变量所属的作用域内声明它们。 - wesbos
1
@evan - 声明a不是多余的。如果在匿名函数中分配给a的行运行之前调用f()而未声明a,将会抛出引用错误。在声明中为a分配值是多余的。 - RobG

1

如果您不想将所需变量作为参数传递,您需要确保调用的函数与定义这些变量的范围相同(或更低)。

因此,在您的情况下,如果您将var f = ...定义放在括号中立即执行的函数内部,它将与变量a处于相同的作用域。我不确定这如何与您提到但未包含在代码示例中的if语句相符,但您可以像这样做:

(function(){
  var f = function(){ alert(a); };

  // other code here if you have any
  var a;

  if ("your if condition" == "something") {
    a = "abc.";
    f();
  }
})();

或者在声明f的地方同时声明a


+1,因为这可能是最好的方法 - 将变量放在作用域链上而不使其成为全局变量。 - RobG

-1

很惊讶没有人说过这个。这就是我会做的事情。

function sayhi () {
    alert("hi " + this.a);
}

(function () {
    this.a = "foo";
    sayhi.call(this);
}());

这个例子实际上什么也没做 - callapply 只是设置了 this 关键字在函数中指向的值。在你的例子中,调用 sayhi()sayhi.call(this) 是相同的,因为两者都将 this 设置为全局上下文 (window)。 - mattsven
1
sayhi.call({a: 'foo'}); 可以工作,但此时为什么不直接传递参数呢? - dansch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接