转自: http://recurial.com/programming/understanding-callback-functions-in-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’reFunction objects created with the Function constructor. AFunction 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 thiskeyword 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 httpRequestobject. 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 to httpRequest.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 thethis 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 theresponseXML 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.

UNDERSTANDING CALLBACK FUNCTIONS IN JAVASCRIPT的更多相关文章

  1. 【JavaScript】Understanding callback functions in Javascript

    Callback functions are extremely important in Javascript. They’re pretty much everywhere. Originally ...

  2. Understand JavaScript Callback Functions and Use Them

    In JavaScript, functions are first-class objects; that is, functions are of the type Object and they ...

  3. 理解callback function in javascript

    以下内容主要摘自[1,2] (1)In javascript, functions are first-class objects, which means functions can be used ...

  4. Understanding RequireJS for Effective JavaScript Module Loading

    Modular programming is used to break large applications into smaller blocks of manageable code. Modu ...

  5. [TypeScript] Simplify asynchronous callback functions using async/await

    Learn how to write a promise based delay function and then use it in async await to see how much it ...

  6. A chatroom for all! Part 1 - Introduction to Node.js(转发)

    项目组用到了 Node.js,发现下面这篇文章不错.转发一下.原文地址:<原文>. ------------------------------------------- A chatro ...

  7. Understanding JavaScript Function Invocation and "this"

    Understanding JavaScript Function Invocation and "this" 11 Aug 2011 Over the years, I've s ...

  8. JavaScript Callback 回调函数

    JavaScript callback回调函数 你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货.在这 ...

  9. 【JavaScript】Registering JavaScript object methods as callbacks

    The registration of callback functions is very common in JavaScript web programming, for example to ...

随机推荐

  1. 8款超绚丽的jQuery焦点图动画

    随着前端技术和浏览器技术的不断发展,人们开始对网页视觉效果的要求越来越高.我们经常会在页面中看到很多炫酷的图片焦点图播放控件,有些甚至是大屏的焦点图占用大片的页面空间,从而吸引用户的眼球.本文要分享的 ...

  2. 《JavaScript高级程序设计》心得笔记-----第二篇章

    第五章 9.Function函数 1)         函数内部有两个特殊的对象: (1)       arguments(主要用于保存函数参数,有一个属性callee,这是一个指针,指向拥有argu ...

  3. Windows Phone 8.1开发:如何从ListView中,获取ScrollViewer对象

    在使用ListView作为信心呈现载体开发应用程序时,我们经常需要通过监视滚动条(ScrollViewer)的位置状态来完成一些交互逻辑.最直接的体现就是 延时加载,(上滑加载更多,下拉获取更新数据) ...

  4. SQL语句执行顺寻

    SQL语句执行的时候是有一定顺序的.理解这个顺序对SQL的使用和学习有很大的帮助. 1.from 先选择一个表,或者说源头,构成一个结果集. 2.where 然后用where对结果集进行筛选.筛选出需 ...

  5. ubuntu 14.04 下 安装samba 及SSH 服务端的方法

    之前说了 FTP服务器的搭建:http://www.cnblogs.com/bcsflilong/p/4200139.html 今天说一下samba 和ssh服务器的搭建. 先说samba 吧. 在u ...

  6. 【Sql Server】使用触发器把一个表中满足条件的数据部分字段插入到另一个表中

    create trigger 触发器名称 on 对哪个表起作用 after insert,update as return set nocount on begin transaction; inse ...

  7. Hibernate之HQL总结

    hibernate运行过程: Hibernate作用 1.hibernate是java应用和关系数据库之间的桥梁,她负责java对象和关系数据库之间的映射. 2.hibernate内部封装了通过JDB ...

  8. 失败经历--在windows下安装meld

    缘起 在linux下,最早用的比较工具是vim,这是作为一个vimer的自尊(其实没有关系吧).终于有一天,在比较同一个项目的两个版本的时候,比较了两三个文件后,看着vim里面花花绿绿的颜色,实在是受 ...

  9. CentOS安装 pure-ftpd

    yum -y install pam-devel cd /usr/local .tar.gz cd pure-ftpd- ./configure --prefix=/usr/local/pure-ft ...

  10. Redis 四:存储类型之列表类型

    .lpush num 依次从左边推入0 - .rpush num 依次从右边推入0 - .lrnage num - 显示num列表中所有的数据 结果: .lpop num 从左边删除并弹出一个元素 . ...