作为函数参数传递的匿名函数的作用域

5

给定以下代码,我应该在警报框中看到什么?

var a = 100;
function afunc(infunc){
  a = 10;
  infunc.call();
}

afunc(function(){alert(a)});

我的初步想法是,因为变量a=100在作为参数传递给afunc的匿名函数中有作用域,所以我的浏览器应该会提示100。但这种假设前提是匿名函数实际上是在全局上下文中定义的。显然事实并非如此,因为浏览器会提示10。那么为什么a=10在作用域链中优先于a=100呢?

谢谢!

3个回答

6

那么为什么在作用域链中 a=10 在 a=100 之前呢?

其实并不是这样的。你只定义了一个 a 变量,它在弹出警告框之前被从 100 更改为 10

如果你想让 a 成为不同的变量并具有自己的值,那么它们都需要使用 var 关键字:

var a = 100
function afunc(infunc){
  var a = 10;
  infunc.call();
}

afunc(function(){alert(a)})​

6

因为在调用匿名函数之前你将 a 设置为了 10。实际上,a 是全局变量,但你将它设置为了 10。


1
考虑以下示例:
var a = 100;

function afunc(infunc){
  a = 10;
  var f = function (){
    console.log(a);
  };
  f.call();
  infunc.call();
}

afunc(function (){ console.log(a); });

afunc的范围内,我们将a的值设为10,然后依次调用两个函数,这些函数只是记录a的值。在这种情况下,你期望这两个函数都会记录a的值为10,并且实际上也确实如此。

在你的例子中,infunc将在与afunc中定义的任何本地函数基本相同的作用域中执行,而不管它实际上是在哪里定义的。由于你在更窄的范围内赋值给了a,所以在调用infunc时,a的值就是这个。

函数确实会保留一些从它们的定义中继承而来的作用域,例如以下示例:

function bfunc(){
  var b = 'hello';
  return function (){ console.log(b); };
}

afunc(bfunc());

在这里,通过 bfunc 返回的匿名函数实际上是在 afunc 的范围内调用的,但它仍然能够记录 b 在原始范围中分配的正确值。如果你要将 afunc 更改为将不同的值分配给 b,它仍将记录 "hello",因为在 bfunc 中定义的 b 是与在 afunc 中定义的 b 不同的变量。

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