我正在阅读 Douglas Crockford 的关于 Javascript 的书,并且对函数作用域部分有一些问题。我的印象是回调函数的 this 值绑定(bind)到调用回调的函数的 this 值(在本例中为 doSomethingAsync)。但是,当我运行此代码时,会打印 foo ,但就 doSomethingAsync 而言, foo 是未定义的。这难道不意味着回调也无权访问这个变量吗?
function doSomething() {
var foo = "foo";
doSomethingAsync(function callback() {
console.log(foo); //prints foo
});
}
最佳答案
this
和变量彼此非常不同。
this
主要由如何调用函数设置,而不是在定义位置设置,尽管绑定(bind)函数和 ES6 的箭头函数改变了这一点(更多内容见下文)。您的回调未绑定(bind),也不是箭头函数,因此您提供的 doSomethingAsync
回调中 this
的值将由 doSomethingAsync 的方式确定
调用该函数。如果它只是将其作为独立函数调用:
callback();
...那么this
将是未定义
(在严格模式下)或对全局对象的引用(在松散模式下)。
但是如果它调用它并指定 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`
...那么这
将会有所不同。
更多(在我的博客上):
不过,函数范围内的变量是由定义该函数的位置决定的。您的回调称为闭包,这意味着它对创建它的上下文(以及周围的上下文,等等,直到并包括全局上下文)有一个持久的引用,包括变量和该上下文中的其他一些东西。因此,当您的回调引用 foo
时,JavaScript 引擎首先在回调中查找,如果没有找到任何名为 foo
的内容,则会查看包含的上下文。在那里找到 foo
,它就会使用它。
但是,闭包所具有的上下文引用不包含this
(箭头函数除外),因为this
更像是一个函数参数比变量(箭头函数除外)。
更多(在我的博客上):
<小时/>“绑定(bind)”函数是从 Function#bind
获得的函数。它们的特点之一是它们的 this
值由您提供的 Function#bind
参数设置,忽略调用它们时提供的参数(如果有)。
ES6“箭头”函数do从创建它们的上下文继承它们的this
,这使得它们与其他类型的函数非常不同。
关于Javascript 回调范围问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30531295/