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.

1 // you can create a function by passing the
2 // Function constructor a string of code
3 var func_multiply = new Function("arg1""arg2""return arg1 * arg2;");
4 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.

01 // define our function with the callback argument
02 function some_function(arg1, arg2, callback) {
03     // this generates a random number between
04     // arg1 and arg2
05     var my_number = Math.ceil(Math.random() *
06         (arg1 - arg2) + arg2);
07     // then we're done, so we'll call the callback and
08     // pass our result
09     callback(my_number);
10 }
11 // call the function
12 some_function(5, 15, function(num) {
13     // this anonymous function will run when the
14     // callback is called
15     console.log("callback called! " + num);
16 });

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):

01 function some_function2(url, callback) {
02     var httpRequest; // create our XMLHttpRequest object
03     if (window.XMLHttpRequest) {
04         httpRequest = new XMLHttpRequest();
05     else if (window.ActiveXObject) {
06         // Internet Explorer is stupid
07         httpRequest = new
08             ActiveXObject("Microsoft.XMLHTTP");
09     }
10  
11     httpRequest.onreadystatechange = function() {
12         // inline function to check the status
13         // of our request
14         // this is called on every state change
15         if (httpRequest.readyState === 4 &&
16                 httpRequest.status === 200) {
17             callback.call(httpRequest.responseXML);
18             // call the callback function
19         }
20     };
21     httpRequest.open('GET', url);
22     httpRequest.send();
23 }
24 // call the function
25 some_function2("text.xml"function() {
26     console.log(this);
27 });
28 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.

http://recurial.com/programming/understanding-callback-functions-in-javascript/

【JavaScript】Understanding callback functions in Javascript的更多相关文章

  1. UNDERSTANDING CALLBACK FUNCTIONS IN JAVASCRIPT

    转自: http://recurial.com/programming/understanding-callback-functions-in-javascript/ Callback functio ...

  2. 【总结】IE和Firefox的Javascript兼容性总结(转)

    文章转自:http://www.cnblogs.com/wiky/archive/2010/01/09/IE-and-Firefox-Javascript-compatibility.html 长久以 ...

  3. 【转】ajax 跨域 headers JavaScript ajax 跨域请求 +设置headers 实践

    解决跨域调用服务并设置headers 主要的解决方法需要通过服务器端设置响应头.正确响应options请求,正确设置 JavaScript端需要设置的headers信息 方能实现. 此处手札 供后人参 ...

  4. 【总结】IE和Firefox的Javascript兼容性总结

    长久以来JavaScript兼容性一直是Web开发者的一个主要问题.在正式规范.事实标准以及各种实现之间的存在的差异让许多开发者日夜煎熬.为此,主要从以下几方面差异总结IE和Firefox的Javas ...

  5. 【JS】369- 20个常用的JavaScript字符串方法

    点击上方"前端自习课"关注,学习起来~ 作者:前端小智 https://segmentfault.com/a/1190000020204425 本文主要介绍一些最常用的JS字符串函 ...

  6. 【repost】学JS必看-JavaScript数据结构深度剖析

    JavaScript以其强大灵活的特点,被广泛运用于各种类型的网站上.一直以来都没怎么好好学JS,只是略懂皮毛,看这篇文章时有读<PHP圣经>的感觉,作者深入浅出.生动形象地用各种实例给我 ...

  7. 【转】45个实用的JavaScript技巧、窍门和最佳实践

    原文:https://colobu.com/2014/09/23/45-Useful-JavaScript-Tips,-Tricks-and-Best-Practices/ 目录 [−] 列表 第一次 ...

  8. 【转】最流行的编程语言JavaScript能做什么?

    本文转自互联网! 首先很遗憾的一点是,“PHP虽然是最好的语言”,但是它不是最流行的语言. 对不起的还有刚刚在4月TIOBE编程语言排行榜上榜的各个语言: 你们都很棒,但是你们都担当不了这个大任. 开 ...

  9. 【原创】web端高德地图javascript API的调用

    关于第三放地图的使用,腾讯.百度.高德 具体怎么选择看你自己怎么选择了. 高德地图开放平台:http://lbs.amap.com/ 本次使用的是高德的javascript API http://lb ...

随机推荐

  1. eclipse 在Navigator视图中查看资源

    随着不断使用Eclipse,Navigator视图中的实体数目会增加.通过在某一项目或文件夹上右击,并在所出现的快捷菜单中选择Go Into命令,你就可以查看该项目或文件夹中的资源了.此时Naviga ...

  2. python程序中自启动appium服务

    普通启动Appium服务方法:      打开cmd,运行命令: #>appium -a 127.0.0.1 -p 4723 当程序输出如上图信息的时候,表示appium启动成功,此时便可以运行 ...

  3. 新霸哥带你进入java的世界

    新霸哥从近期大家的留言中注意到了大家对基础知识比较重视,很多的朋友希望多讲一些入门的知识,为了满足广大开发爱好者的需求,新霸哥决定从最基础的做起,一点一点的帮助大家一起走进云计算的世界.下面新霸哥首先 ...

  4. 《学习OpenCV》练习题第四章第三题b

    #include <highgui.h> #include <cv.h> #include "opencv_libs.h" /* *<学习OpenCV ...

  5. 第三百三十一天 how can I 坚持

    今天加了一天班,好累,还没吃晚饭,回来只吃了个泡面. 晚上回来的路上,在群里聊的倒是很happy,快笑死我了,仲宫二少,哈哈. 弟弟过两天要去见面,多聊聊,该结婚来. 还有,中午吃的肯德基,不好吃,可 ...

  6. VMare中安装“功能增强工具”,实现CentOS5.5与win7host共享文件夹的创建

    读者如要转载,请标明出处和作者名,谢谢. 地址01:http://space.itpub.net/25851087 地址02:http://www.cnblogs.com/zjrodger/ 地址03 ...

  7. Unity2D Keynote

    [Unity2D Keynote] 1.File Format Accepted by Unity 2.By double-clicking an object in Hierachy, you no ...

  8. C++11for循环

    [C++11for循环] for 述句将允许简单的范围迭代,引用或非引用形式均可: 参考:http://zh.wikipedia.org/wiki/C++0x

  9. keil中如何得知所编译程序所占空间大小?

    keil编译后出现Program Size: data=21.0 xdata=0 code=2231. 这表明 data= 21.0  数据储存器内部RAM占用21字节, xdata=0     数据 ...

  10. HDU 1312 Red and Black DFS(深度优先搜索) 和 BFS(广度优先搜索)

    Red and Black Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...