简体   繁体   English

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

[英]Are javascript callbacks just anonymous functions sent as an argument in a function call?

Are Javascript callbacks just anonymous functions sent as an argument in a function call? Javascript callbacks只是作为函数调用中的参数发送的匿名函数吗?

For example,例如,

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

JavaScript callbacks are functions passed as values into an asynchronous function for the purpose of continuation. JavaScript 回调是作为值传递给异步函数的函数,目的是继续执行。

Functions are values:函数是值:

So in JavaScript, you can pass a functions around like values.因此,在 JavaScript 中,您可以传递类似值的函数。 You can reference a function in a number of ways:您可以通过多种方式引用函数:

  1. Pass a literal anonymous function as the callback传递一个文字匿名函数作为回调

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

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

    ( Naming every function is a smart idea because you can see it in the stack trace ) 命名每个函数是一个聪明的主意,因为您可以在堆栈跟踪中看到它

  3. Pass in the value of a variable which happens to be storing a function as the callback传入一个变量的值,该变量恰好将函数存储为回调

    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. Pass in the function by referencing the function name as the callback通过引用函数名作为回调函数传入函数

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

Continuation?继续?

Continuation is all about the next step.继续就是下一步。 When you call a function which is asynchronous, it needs to notify you that it is done.当你调用一个异步函数时,它需要通知你它已经完成。 The callback acts as the next step, ie the asynchronous function will call you back when it is done.回调作为下一步,即异步函数将在完成后回调您。

So a callback is just a function argument used for a particular purpose, that being, continuation.所以回调只是一个用于特定目的的函数参数,即延续。

Callback signature回调签名

There is no standard for which arguments a callback should take, but in the Node.js community we have adopted the general signature回调应该采用哪些参数没有标准,但在 Node.js 社区中,我们采用了通用签名

function (err, result)

where err is an Error object if something bad happened, or null if things were successful.如果发生了不好的事情, err是一个Error对象,如果事情成功,则为null If things went bad result is generally undefined , otherwise it contains the result.如果事情变得糟糕result通常是undefined ,否则它包含结果。 So your callback is generally called by either所以你的回调通常由任何一个调用

callback(new Error("oops"));

or或者

callback(null, result);

Also note that it's normal for the last parameter of an asynchronous function to be the callback parameter另请注意,异步函数的最后一个参数作为回调参数是正常的

function callLater(delay, args, callback) {
    setTimeout(function () {     
        callback(null, args);
    }, delay);
}

In your example: yes在您的示例中:是

But in m example: No但在 m 示例中:否

function myCallback()
{
    alert('finished eating my sandwich');
}
mySandwich('ham','cheese', myCallback);

So, from you comment I think the real question is: What is an anonymous function?所以,根据你的评论,我认为真正的问题是:什么是匿名函数? I did my best, but it is still early in the morning here, so don't shoot me.我已经尽力了,但这里现在还早,所以不要开枪。

Well, gooed question.嗯,很好的问题。 Hard answer硬回答

when defining a function, it lives withing its scope .在定义一个函数时,它存在于它的scope Scope?范围? huh?嗯? Ok, let's start again.好吧,让我们重新开始。

when a webpage is loaded, the browser creates a window object.加载网页时,浏览器会创建一个窗口对象。 It then starts parsing everything you wrote in that document (let's assume HTML).然后它开始解析您在该文档中编写的所有内容(假设为 HTML)。

Every DOMElement it encounters, gets put into the window.document object.它遇到的每个 DOMElement 都会被放入window.document对象中。 Every Element inside the widnow.document element is rendered/interpreted in your browser window. widnow.document 元素中的每个元素都在浏览器窗口中呈现/解释。

Now, the browser encounters the following <script> :现在,浏览器遇到以下<script>

var myVariable = 'So cool';

The browser sees var myVariable .浏览器看到var myVariable This tells him to create a variable called myVariable in the current scope (again that word).这告诉他在当前范围内创建一个名为myVariable的变量(还是那个词)。 the current scope is window (the window object the browser created).当前范围是window (浏览器创建的窗口对象)。 So it adds the variable to the window object:所以它将变量添加到 window 对象中:

window.myVariable === myVariable

The same goes for functions函数也是一样

function myAwesomeFunction()
{
    alert('I am so cool');
}

Creates a function inside the current scope ( window ) with the name myAwesomeFunction .在当前作用域( window )内创建一个名为myAwesomeFunction So again:再说一遍:

window.myAwesomeFunction === myAwesomeFunction

But what if I want to create a function I don't whant any other code to have access to?但是如果我想创建一个我不希望任何其他代码访问的函数怎么办? What if I want a function that should only exist when a certain specific button is clicked.如果我想要一个只有在单击某个特定按钮时才应该存在的功能,该怎么办。

Well, enter anonymous functions.好吧,输入匿名函数。 these are functions that are declared in the anonymous scope.这些是在匿名范围内声明的函数。 they cannot be accessed using the window object:不能使用 window 对象访问它们:

myButton = document.getElementById('myButton'); // === window.document.getElementById('myButton');
myButton.addEventListener('click', function()
{
    alert('I am so awesome');
});

Now, the function you passed into the eventlistener only lives inside the eventListener.现在,您传递给 eventlistener 的函数只存在于 eventListener 中。 It doesn't even have a name.它甚至没有名字。 So it's scope is 'the on click event of the button' but we can't access it from outside because it doesnt have a name.所以它的作用域是“按钮的点击事件”,但我们不能从外部访问它,因为它没有名字。 Thus, anonymous function.因此,匿名函数。

A good read would be to google stuff like 'javascript scope', 'javascript window object', ... A lot of good articles give a better in depth explanation of all the words I threw at you.一个很好的读物是谷歌的东西,比如“javascript scope”、“javascript window object”……很多好文章对我扔给你的所有词提供了更好的深入解释。

Yes, except that they don't have to be anonymous functions, and there's a bit more to the definition of a callback.是的,除了它们不必是匿名函数,而且回调的定义还有一点。 The other two answers have covered the details of what callbacks are for and anonymous functions well, but I have had similar confusion to yours when I was first learning so I wanted to add a missing piece.另外两个答案已经很好地涵盖了回调的用途和匿名函数的详细信息,但是当我第一次学习时,我也遇到了与您类似的困惑,所以我想添加一个缺失的部分。 So, your example:所以,你的例子:

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

I've noticed most callback explanations are like this- they don't include the declaration of the larger function, in this case mySandwich.我注意到大多数回调解释都是这样的——它们不包括更大函数的声明,在这种情况下是 mySandwich。 But yes, the function this is being passed into does need to explicitly call the callback function for it to run.但是是的,传入的函数确实需要显式调用回调函数才能运行。 So your mySandwich function might look like this:因此,您的 mySandwich 函数可能如下所示:

function mySandwich(meat, topping, callback) {
    //some code here using meat and topping
    //some code here about eating the sandwich
    callback();
}

So your code passes those parameters, including the function, into the mySandwich function, which then invokes it.因此,您的代码将这些参数(包括函数)传递到 mySandwich 函数中,然后该函数调用它。 Because many times the top-level function we are using is a method from a library rather than part of our own code, we don't actually see the step where the callback is invoked, but it does still happen and doesn't just automatically execute itself.因为很多时候我们使用的顶级函数是来自库的方法而不是我们自己代码的一部分,所以我们实际上并没有看到调用回调的步骤,但它仍然会发生并且不会自动发生执行自己。

So yes, a callback is really just a function being passed as a parameter to another function, and then it is invoked usually as the last thing to happen in that larger function.所以是的,回调实际上只是一个作为参数传递给另一个函数的函数,然后它通常作为该更大函数中发生的最后一件事被调用。 There's more than that to callbacks, but they operate by the same rules as other functions in that somewhere they have to be declared and somewhere they have to be called, otherwise they don't run.回调不止于此,但它们的操作规则与其他函数相同,因为它们必须在某处被声明,在某处必须被调用,否则它们不会运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM