我正在阅读道格拉斯·克罗克福德(Douglas Crockford)关于Javascript的书,并对函数范围部分提出了一些问题。我的印象是回调函数的这个值绑定到调用回调函数的这个值(在这种情况下是doSomethingAsync)。但是,当我运行此代码时,会打印foo,但就doSomethingAsync而言,foo是未定义的。这不应该意味着回调也无法访问此var吗?
function doSomething() {
var foo = "foo";
doSomethingAsync(function callback() {
console.log(foo); //prints foo
});
}
答案 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,那么将使用该变量。