javascript 回调函数
2012-09-24 23:15 youxin 阅读(367) 评论(0) 编辑 收藏 举报什么是回调函数?wikipedia定义。
A reference to executable code, or a piece of executable code, that is passed as an argument to other code.
Here’s a simple example that’s probably quite familiar to everyone, taken from jQuery:
$('#element').fadeIn('slow', function() { // callback function });
This is a call to jQuery’s fadeIn() method. This method accepts two arguments: The speed of the fade-in and an optional callback function. In that function you can put whatever you want.
When the fadeIn()
method is completed, then the callback function (if present) will be executed. So, depending on the speed chosen, there could be a noticeable delay before the callback function code is executed. You can read more about jQuery’s callback functions here.
How to Write a Callback Function
If you’re writing your own functions or methods, then you might come across a need for a callback function. Here’s a very simple example of a custom callback function:
function mySandwich(param1, param2, callback) { alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2); callback(); } mySandwich('ham', 'cheese', function() { alert('Finished eating my sandwich.'); });
Here we have a function called mySandwich
and it accepts three parameters. The third parameter is the callback function. When the function executes, it spits out an alert message with the passed values displayed. Then it executes the callback function.
Notice that the actual parameter is just “callback” (without parentheses), but then when the callback is executed, it’s done using parentheses. You can call this parameter whatever you want, I just used “callback” so it’s obvious what’s going on.
The callback function itself is defined in the third argument passed to the function call. That code has another alert message to tell you that the callback code has now executed. You can see in this simple example that an argument passed into a function can be a function itself, and this is what makes callbacks possible in JavaScript.
Here’s a JSBin that uses the simple example above.
Make the Callback Optional
One thing you’ll notice about jQuery callbacks is that they’re optional. This means if a method accepts a callback, it won’t return an error if a callback is not included. In our simple example, the page will return an error if we call the function without a callback, like this:
mySandwich('ham', 'cheese');
You can see this in action here. If you open your developer tools, you’ll see an error that says “undefined is not a function” (or something similar) that appears after the initial alert message.
To make the callback optional, we can just do this:
function mySandwich(param1, param2, callback) { alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2); if (callback) { callback(); } } mySandwich('ham', 'cheese');
Now, since we’re checking to ensure the existence of callback
, the function call won’t cause an error without it. You can test this example here.
Make Sure the Callback is a Function
Finally, you can ensure that whatever value is passed as the third argument is in fact a proper function, by doing this:
function mySandwich(param1, param2, callback) { alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2); if (callback && typeof(callback) === "function") { callback(); } } mySandwich('ham', 'cheese', 'vegetables');
Notice that the function now includes a test using the typeof
operator, to ensure that whatever is passed is actually a function. The function call has a third argument passed, but it’s not a function, it’s a string. So the test usingtypeof
ensures no error occurs.
Here’s a JSBin with a nonfunction argument passed as the callback.
A Note About Timing
Although it is true that a callback function will execute last if it is placed last in the function, this will not always appear to happen. For example, if the function included some kind of asynchronous execution (like an Ajax call or an animation), then the callback would execute after the asynchronous action begins, but possibly before it finishes.如果函数包含异步调用函数,回调函数可能发生在异步函数之后或之前。
Here’s an example that uses jQuery’s animate
method:
function mySandwich(param1, param2, callback) { alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2); $('#sandwich').animate({ opacity: 0 }, 5000, function() { // Animation complete. }); if (callback && typeof(callback) === "function") { callback(); } } mySandwich('ham', 'cheese', function() { alert('Finished eating my sandwich.'); });
And again here’s that code live.
Notice that although the callback appears later in source order than the animation, the callback will actually execute long before the animation completes. In this case, solving this problem is easy: You just put the callback execution inside the animate
method’s callback function (where it says “Animation complete”).尽管回调函数出现在animation之后,但实际在动画结束前执行,解决这个问题是很容易的,把回调函数放在animate的参数里。
This doesn’t cover all the details regarding asynchronous functions, but it should serve as a basic warning that callback functions will only execute last as long as all the code in the function is synchronous.
via:http://www.impressivewebs.com/callback-functions-javascript/
另一篇文章:
Callback functions are extremely important in Javascript. They’re pretty much everywhere. Originally coming from a more traditional C/Java background I had trouble with this (and the whole idea of asynchronous programming), but I’m starting to get the hang of it. Strangely, I haven’t found any good introductions to callback functions online — I mainly found bits of documentation on the call() and apply() functions, or brief code snippits demonstrating their use — so, after learning the hard way I decided to try to write a simple introduction to callbacks myself.
Functions are objects 函数就是对象
To understand callback functions you first have to understand regular functions. This might seen like a “duh废话” thing to say, but functions in Javascript are a bit odd.
Functions in Javascript are actually objects. Specifically, they’re Function
objects created with the Function
constructor. A Function
object contains a string which contains the Javascript code of the function. If you’re coming from a language like C or Java that might seem strange (how can code be a string?!) but it’s actually run-of-the-mill for Javascript. The distinction between code and data is sometimes blurred.
// you can create a function by passing the // Function constructor a string of code var func_multiply = new Function("arg1", "arg2", "return arg1 * arg2;"); func_multiply(5,10); // => 50
One benefit of this function-as-object concept is that you can pass code to another function in the same way you would pass a regular variable or object (because the code is literally just an object).
Passing a function as a callback
Passing a function as an argument is easy.
// define our function with the callback argument function some_function(arg1, arg2, callback) { // this generates a random number between // arg1 and arg2 var my_number = Math.ceil(Math.random() * (arg1 - arg2) + arg2); // then we're done, so we'll call the callback and // pass our result callback(my_number); } // call the function some_function(5, 15, function(num) { // this anonymous function will run when the // callback is called console.log("callback called! " + num); });
It might seem silly to go through all that trouble when the value could just be returned normally, but there are situations where that’s impractical and callbacks are necessary.
Don’t block the way
Traditionally functions work by taking input in the form of arguments and returning a value using a return statement (ideally a single return statement at the end of the function: one entry point and one exit point). This makes sense. Functions are essentially mappings between input and output.
Javascript gives us an option to do things a bit differently. Rather than wait around for a function to finish by returning a value, we can use callbacks to do it asynchronously. This is useful for things that take a while to finish, like making an AJAX request, because we aren’t holding up the browser. We can keep on doing other things while waiting for the callback to be called. In fact, very often we are required (or, rather, strongly encouraged) to do things asynchronously in Javascript.
Here’s a more comprehensive example that uses AJAX to load an XML file, and uses the call() function to call a callback function in the context of the requested object (meaning that when we call the this
keyword inside the callback function it will refer to the requested object):
function some_function2(url, callback) { var httpRequest; // create our XMLHttpRequest object if (window.XMLHttpRequest) { httpRequest = new XMLHttpRequest(); } else if (window.ActiveXObject) { // Internet Explorer is stupid httpRequest = new ActiveXObject("Microsoft.XMLHTTP"); } httpRequest.onreadystatechange = function() { // inline function to check the status // of our request // this is called on every state change if (httpRequest.readyState === 4 && httpRequest.status === 200) { callback.call(httpRequest.responseXML); // call the callback function } }; httpRequest.open('GET', url); httpRequest.send(); } // call the function some_function2("text.xml", function() { console.log(this); }); console.log("this will run before the above callback");
In this example we create the httpRequest
object and load an XML file. The typical paradigm of returning a value at the bottom of the function no longer works here. Our request is handled asynchronously, meaning that we start the request and tell it to call our function when it finishes.
We’re using two anonymous functions here. It’s important to remember that we could just as easily be using named functions, but for sake of brevity they’re just written inline. The first anonymous function is run every time there’s a state change in our httpRequest
object. We ignore it until the state is 4 (meaning it’s done) and the status is 200 (meaning it was successful). In the real world you’d want to check if the request failed, but we’re assuming the file exists and can be loaded by the browser. This anonymous function is assigned tohttpRequest.onreadystatechange
, so it is not run right away but rather called every time there’s a state change in our request.
When we finally finish our AJAX request, we not only run the callback function but we use the call()
function. This is a different way of calling a callback function. The method we used before of just running the function would work fine here, but I thought it would be worth demonstrating the use of the call()
function. Alternatively you could use the apply()
function (the difference between the two is beyond the scope of this tutorial, but it involves how you pass arguments to the function).
The neat thing about using call()
is that we set the context in which the function is executed. This means that when we use the this
keyword inside our callback function it refers to whatever we passed as the first argument for call()
. In this case, when we refer to this inside our anonymous callback function we are referring to the responseXML
from the AJAX request.
Finally, the second console.log statement will run before the first, because the callback isn’t executed until the request is over, and until that happens the rest of the code goes right on ahead and keeps running.
Wrapping it up
Hopefully now you should understand callbacks well enough to use them in your own code. I still find it hard to structure code that is based around callbacks (it ends up looking like spaghetti… my mind is too accustomed to regular structured programming), but they’re a very powerful tool and one of the most interesting parts of the Javascript language.
via:http://recurial.com/programming/understanding-callback-functions-in-javascript/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现