Javascript
callbacks
只是在函数调用中作为参数发送匿名函数吗?
例如,
mySandwich('ham', 'cheese', function() {
alert('Finished eating my sandwich.');
});
答案 0 :(得分:3)
在你的例子中:是的
但是在例子中:没有
function myCallback()
{
alert('finished eating my sandwich');
}
mySandwich('ham','cheese', myCallback);
所以,从你的评论我认为真正的问题是:什么是匿名函数?我尽我所能,但现在还很早,所以不要开枪。
嗯,糟糕的问题。硬答案
在定义函数时,它与scope
一起生效。范围?是吧?好的,让我们重新开始吧。
加载网页时,浏览器会创建一个window对象。然后它开始解析你在该文档中写的所有内容(让我们假设HTML)。
遇到的每个DOMElement都会被放入window.document对象中。 widnow.document元素中的每个元素都在浏览器窗口中呈现/解释。
现在,浏览器遇到以下<script>
:
var myVariable = 'So cool';
浏览器会看到var myVariable
。这告诉他在当前作用域中创建一个名为myVariable
的变量(同样是该单词)。当前范围是window
(浏览器创建的窗口对象)。所以它将变量添加到窗口对象:
window.myVariable === myVariable
功能
也是如此function myAwesomeFunction()
{
alert('I am so cool');
}
在当前范围(window
)内创建一个名为myAwesomeFunction
的函数。再说一次:
window.myAwesomeFunction === myAwesomeFunction
但是,如果我想创建一个我不想访问任何其他代码的函数怎么办?如果我想要一个仅在单击某个特定按钮时才存在的功能,该怎么办?
好吧,输入匿名函数。这些是在匿名范围内声明的函数。使用window对象无法访问它们:
myButton = document.getElementById('myButton'); // === window.document.getElementById('myButton');
myButton.addEventListener('click', function()
{
alert('I am so awesome');
});
现在,传递给eventlistener的函数只存在于eventListener中。它甚至没有名字。所以它的范围是按钮的点击事件&#39;但我们无法从外部访问它,因为它没有名称。因此,匿名函数。
一个很好的阅读方式是google的内容,例如“javascript范围&#39;”,“javascript窗口对象”,...很多好的文章都会对所有的文章进行更好的深入解释我扔给你的话。
答案 1 :(得分:2)
JavaScript回调函数是作为值传递给异步函数的函数,用于继续。
因此,在JavaScript中,您可以像值一样传递函数。您可以通过多种方式引用功能:
传递一个文字匿名函数作为回调
doSomeWork(function (err, result) {
if (err) {
throw new Error(err);
} else {
console.log(result);
}
});
传递一个文字命名函数作为回调
doSomeWork(function magicalCallback(err, result) {
if (err) {
throw new Error(err);
} else {
console.log(result);
}
});
(命名每个函数都是一个明智的想法,因为你可以在堆栈跟踪中看到它)
传入恰好存储函数的变量值作为回调
var someFunction = function callItWhatYouWant(err, result) {
if (err) {
throw new Error(err);
} else {
console.log(result);
}
}
// reference the callback stored in the someFunction variable
doSomeWork(someFunction);
通过引用函数名称作为回调来传递函数
function callItWhatYouWant(err, result) {
if (err) {
throw new Error(err);
} else {
console.log(result);
}
}
// reference the callback function using the function name
doSomeWork(callItWhatYouWant);
继续就是下一步。当您调用异步函数时,它需要通知您它已完成。回调充当下一步,即异步函数将在完成后回调。
因此回调只是用于特定目的的函数参数,即延续。
回调应该采用哪些参数的标准,但在Node.js社区中我们采用了一般签名
function (err, result)
如果发生了错误,err
是Error
对象,如果成功则发生null
。如果情况变得糟糕result
通常是undefined
,否则它会包含结果。因此,您的回调通常由
callback(new Error("oops"));
或
callback(null, result);
另请注意,异步函数的最后一个参数是回调参数
是正常的function callLater(delay, args, callback) {
setTimeout(function () {
callback(null, args);
}, delay);
}
答案 2 :(得分:0)
是的,除了它们不必是匿名函数外,回调的定义还有很多。其他两个答案已经很好地说明了回调的用途和匿名函数的详细信息,但是当我初次学习时,我与您的困惑相似,因此我想添加一个遗漏的部分。因此,您的示例:
mySandwich('ham', 'cheese', function() {
alert('Finished eating my sandwich.');
});
我注意到大多数回调解释都是这样的-它们不包括较大函数的声明,在本例中为mySandwich。但是,是的,要传递给它的函数确实需要显式调用回调函数才能运行。因此,您的mySandwich函数可能如下所示:
function mySandwich(meat, topping, callback) {
//some code here using meat and topping
//some code here about eating the sandwich
callback();
}
因此,您的代码将这些参数(包括函数)传递到mySandwich函数中,然后调用该函数。因为很多时候我们使用的顶层函数是库中的方法,而不是我们自己代码的一部分,所以我们实际上看不到调用回调的步骤,但是它仍然会发生并且不仅会自动自行执行。
所以,是的,回调实际上只是一个作为参数传递给另一个函数的函数,然后通常在该更大的函数中发生的最后一件事被调用。回调的功能远不止于此,但是它们与其他函数所遵循的规则相同,因此必须在某些地方声明和调用它们,否则它们将不会运行。