多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
我们在学习其它语言时,在调用一个函数时,往往是如下这样的: ~~~ // 定义 function yunzhi(string name, int sex, array friends) { ..... } // 调用 yunzhi('zhangsan', 1, array('lisi', 'wangwu')); ~~~ 而很少见过下面这种调用形式: ~~~ yunzhi('hello', function(){}); ~~~ > 在JavaScript中,作为参数传入的函数,我们称之为回调函数。 我们看下JavaScript中对回调函数是这样定义的: > A callback is a function that is passed as an argument to another function and is executed after its parent function has completed. 简单翻一下,回调函数就是回头再调用的函数。 举个简单例子: 假设现在有函数a()和函数b(): **C语言中**: a(b()); //b()被作为a()的参数传入,先执行b(),再执行a()。 **JavaScript中**: a(b()); //b()被作为a()的参数(回调函数)传入,先执行a(),由a()决定b()的执行情况(b()可能被执行一次或多次,也可能一次也不执行,可能一开始就被执行,也可能最后被执行,一切全凭a()的心情)。 这里看不懂没关系,我们下面用代码的方式详细说明一下。 # 传函数 以前,我们只将普通的变量传到另一个函数中,变量的类型可能是int、string、array,还可能是object,但还没有把函数看做一个变量作为参数传过去。 下面,我们来共同看看在JS中函数是怎么作为参数被传过去,并且在函数中被正确执行的。 为此,我们在根文件夹下新建一个test.html文件。 测试代码如下: `test.html` ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <script type="text/javascript"> // 定义yunzhi var yunzhi = function(callback) { // 执行传入的函数 callback callback(); } // 定义hello,控制台输出hello var hello = function(){ console.log('hello'); }; // 将hello做为参数传入yunzhi yunzhi(hello); </script> </body> </html> ~~~ 测试: ![](https://box.kancloud.cn/2016-07-20_578f39333dfd4.png) 没错,在JS中,函数做为参数传入后就这么被执行了。 下面,我们再简单改写下。 ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <script type="text/javascript"> // 定义yunzhi var yunzhi = function(callback) { // 执行传入的函数 callback callback(); } // 由于yunzhi接收的参数类型为function // 我们在这直接写下一个function也是可以的 yunzhi(function(){}); </script> </body> </html> ~~~ 再改写: ~~~ ... // 由于yunzhi接收的参数类型为function // 我们在这直接写下一个function也是可以的 yunzhi(function(){ console.log('hello'); }); </script> ... ~~~ 刷新面页,我们发现实现的效果相同。 ## 引入对象 为了更好的理解在angularjs中定义模块和控制器的写法。我们再给出另一个示例:定义一个yunzhi对象,对象中有3个属性:name、sex、fn,类型分别为string、int和function。 ~~~ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>test</title> </head> <body> <script type="text/javascript"> // 定义一个对象 var yunzhi = { name:'hello', sex:1, fn:function(){} } </script> </body> </html> ~~~ 既然fn的类型是function,那么当然是可以这样定义: ~~~ fn:function(){ console.log('I am a function'); } ~~~ 然后我们这样来调用: ~~~ yunzhi.fn(); ~~~ 当然了,name和sex也是可以定义为function的。我们再改写: ~~~ var yunzhi = { name:'hello', sex:1, fn:function(){ console.log('I am function'); }, setName: function(){}, setSex: function(){} } ~~~ 再改写: ~~~ setName: function(name, callback){ this.name = name; // 设置当前对象的name callback; // 执行回调 return this; // 返回当前对象 }, ~~~ 继续改写setSex: ~~~ var yunzhi = { name:'hello', sex:1, fn:function(){ console.log('I am function'); }, setName: function(name, callback){ this.name = name; // 设置当前对象的name callback; // 执行回调 return this; // 返回当前对象 }, setSex: function(sex, callback){ this.sex = sex; callback; return this; } } ~~~ 最后,我们如下调用: ~~~ var yunzhi = { name:'hello', sex:1, fn:function(){ console.log('I am function'); }, setName: function(name, callback){ this.name = name; // 设置当前对象的name callback(); // 执行回调 return this; // 返回当前对象 }, setSex: function(sex, callback){ this.sex = sex; callback(); return this; } } // 调用yunzhi中的setName方法,得到一个对象。 var zhangsan = yunzhi.setName('zhangsan', function(){}); // 调用对象中的sexSex方法 zhangsan.setSex(0, function(){}); ~~~ 最后,我们向function中加入我们想执行的回调代码。 > 没错,一个好的书写习惯,不仅可以提升代码的效率,还可以提升我们写代码的准确性。更重要的是,我们可以更好的理解代码之间互相调用的关系。当我们在接解一门新的语言时,就显得更加重要了。 ~~~ // 调用yunzhi中的setName方法,得到一个对象。 var zhangsan = yunzhi.setName('zhangsan', function(){ console.log('set name zhangsan success'); }); // 调用对象中的sexSex方法 zhangsan.setSex(0, function(){ console.log('set sex 0 success'); }); ~~~ 执行结果: ![](https://box.kancloud.cn/2016-07-20_578f39335db2f.png) ## 为什么要用回调 1、回调函数的执行需要依赖前面函数的执行结果。 基于此,我们再改写,让其更贴近我们前面看到的angularjs初始化模块及控制器的代码。 ~~~ setName: function(name, callback){ this.name = name; // 设置当前对象的name var message = 'set name ' + name + 'success'; callback(message); // 执行回调 return this; // 返回当前对象 }, ... // 调用yunzhi中的setName方法,得到一个对象。 var zhangsan = yunzhi.setName('zhangsan', function(message){ console.log(message); }); ~~~ 最终的执行结果与未改写前是一致的。 现在,在让我们回想一下angularjs的写法: ~~~ // 调用 angular对象的module方法,该方法接收两个参数。第一个是模块名,第二个数组,返回值是一个对象。 var module = angular.module('modulename', []); // 调用上面返回对象的controller方法,该方法接收两个参数,第一个参数类型是字符串,第二个类型是function。 module.controller('controllerName', function(){}); // 我们还可以在function中加入参数及代码实现 module.controller('controllerName', function($scope){ .... }); ~~~ 如果看懂了,那么恭喜你。如果没看懂,那么就再看一遍,跟着写一下测试代码。当然了,如果你看了几遍还没有懂,我想应该是我教程的问题了。那就不要再纠结,直接看下一节好了。