Javascript回调范围问题

时间:2015-05-29 13:47:19

标签: javascript function scope

我正在阅读道格拉斯·克罗克福德(Douglas Crockford)关于Javascript的书,并对函数范围部分提出了一些问题。我的印象是回调函数的这个值绑定到调用回调函数的这个值(在这种情况下是doSomethingAsync)。但是,当我运行此代码时,会打印foo,但就doSomethingAsync而言,foo是未定义的。这不应该意味着回调也无法访问此var吗?

function doSomething() {
  var foo = "foo";
  doSomethingAsync(function callback() {
    console.log(foo); //prints foo
  });
}

2 个答案:

答案 0 :(得分:3)

this和变量彼此非常不同。

this主要由如何调用函数设置,而不是在其定义的位置设置,尽管绑定函数和ES6的箭头函数会改变它(更多信息如下) )。您的回调未受约束且不是箭头功能,因此您在this回调中的doSomethingAsync值将由doSomethingAsync决定调用那个函数。如果它将其称为独立功能:

callback();

...然后this将是undefined(在严格模式下)或对全局对象的引用(在松散模式下)。

但如果它称之为指定this值:

// By making it an object property and using that to call it:
var obj = {callback: callback};
obj.callback(); // `this` will be `obj`

// By using Function#call or Function#apply
callback.call(foo); // `this` will be `foo`

...然后this会有所不同。

更多(在我的博客上)

但是,函数范围内的变量由定义函数的位置决定。您的回调称为闭包,这意味着它具有对其创建的上下文的持久引用(以及围绕该上下文的上下文,依此类推,包括全局上下文),包括变量和该上下文中的一些其他东西。因此,当您的回调引用foo时,JavaScript引擎首先在回调中查找,并且找不到任何名为foo的内容,查看包含的上下文。在那里找到foo,它会使用它。

闭包的上下文引用包括this,但是(箭头函数除外),因为this更像是函数参数而不是变量(除了对于箭头功能)。

更多(在我的博客上)

"结合"函数是从Function#bind获得的函数。它们的一个特点是它们的this值是由您给出的参数Function#bind设置的,忽略了它们被调用时提供的参数(如果有的话)。

ES6" arrow"函数 do 从创建它们的上下文继承它们的this,使它们与其他类型的函数非常不同。

答案 1 :(得分:1)

首先,回调函数检查它是否有任何" foo" var在自己的范围内。 当它发现没有任何东西时,它会检查它的父母"范围为" foo"变种。 它在那里找到并使用它。

如果在回调中定义一个新的var foo,那么将使用该变量。