javascript回调只是在函数调用中作为参数发送的匿名函数吗?

时间:2014-05-27 06:07:41

标签: javascript

Javascript callbacks只是在函数调用中作为参数发送匿名函数吗?

例如,

mySandwich('ham', 'cheese', function() {  
   alert('Finished eating my sandwich.');  
  }); 

3 个答案:

答案 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中,您可以像值一样传递函数。您可以通过多种方式引用功能:

  1. 传递一个文字匿名函数作为回调

    doSomeWork(function (err, result) {
        if (err) {
            throw new Error(err);
        } else {
            console.log(result);
        }
    });
    
  2. 传递一个文字命名函数作为回调

    doSomeWork(function magicalCallback(err, result) {
        if (err) {
            throw new Error(err);
        } else {
            console.log(result);
        }
    });
    

    命名每个函数都是一个明智的想法,因为你可以在堆栈跟踪中看到它

  3. 传入恰好存储函数的变量值作为回调

    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);
    
  4. 通过引用函数名称作为回调来传递函数

    function callItWhatYouWant(err, result) {
        if (err) {
            throw new Error(err);
        } else {
            console.log(result);
        }
    }
    
    // reference the callback function using the function name
    doSomeWork(callItWhatYouWant);
    
  5. 延续?

    继续就是下一步。当您调用异步函数时,它需要通知您它已完成。回调充当下一步,即异步函数将在完成后回调。

    因此回调只是用于特定目的的函数参数,即延续。

    回拨签名

    回调应该采用哪些参数的标准,但在Node.js社区中我们采用了一般签名

    function (err, result)
    

    如果发生了错误,errError对象,如果成功则发生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函数中,然后调用该函数。因为很多时候我们使用的顶层函数是库中的方法,而不是我们自己代码的一部分,所以我们实际上看不到调用回调的步骤,但是它仍然会发生并且不仅会自动自行执行。

所以,是的,回调实际上只是一个作为参数传递给另一个函数的函数,然后通常在该更大的函数中发生的最后一件事被调用。回调的功能远不止于此,但是它们与其他函数所遵循的规则相同,因此必须在某些地方声明和调用它们,否则它们将不会运行。