JavaScript中的回调函数
在学习JavaScript的过程中遇到了很多,使用到回调函数的例子,出现了许多疑问,就由一个栗子开始吧:
在JavaScript中接触的第一个回调函数是在setInterval()和setTimeout()中出现的:
1 var num = 10; 2 3 var interValId = setInterval(function (){ 4 console.log(num); 5 num--; 6 if(num==0){ 7 clearInterval(interValId); 8 } 9 },1000);
代码中实现了使用了setInterval()在控制台打印数值,然后当数值变为0的时候停止打印。
在使用setInterval()的时候使用了一个匿名函数作为回调函数,当时看到这,就懵掉了,
此匿名函数没有实参列表,也就是说这是一个函数声明,不是调用,而且这个匿名函数写在setInterval()的形参列表位置,说明它是setInterval()的形参,但是这个函数是在什么时候调用的呢,如果这个函数也需要传参呢,在调用这个匿名函数的时候,又是怎样实现参数传递的呢。
再一次遇见它是在学习DOM2中使用addEventListener()进行事件绑定的时候:
1 btn2.addEventListener("click",function (){ 2 btn1.removeEventListener("click",func1) 3 },false)
在取消事件绑定的时候,有个要求,就是removerEventListener()中的回调函数不能是匿名函数。但是问题还是没有解决,接下来又遇到了有形参列表的回调函数:
数组中的排序函数:sort();
1 arr3.sort(function(a,b){ 2 //return a-b; // b在前,a在后(升序排列) 3 return b-a; // a在前,b在后(降序排列) 4 });
这次的回调函数竟然有了形参,但是问题还是那个问题,这里的形参a,b什么时候变为实参的?他们被赋予实参的时候,赋的值又是什么呢?
所有的可能性都被排除了,只有一种就是,sort()这个函数给回调函数的参数进行赋值,并把回调函数进行了调用,这样就要求,回调函数的函数声明必须按照调用它的函数的规定进行编写,就是调用它的函数需要它完成什么样的功能,回调函数的函数体应该是怎样的,而且它的参数也不能乱写,必须按照规定写形参,他在调用的时候,传了几个实参,就要写几个形参。
在使用系统已经写好的函数中编写回调函数的时候,程序员们需要完成的部分,只是回调函数的声明部分,而且参数必须按照规定写。
函数也是对象
想弄明白回调函数,首先的清楚地明白函数的规则。在javascript中,函数是比较奇怪的,但它确确实实是对象。确切地说,函数是用function()构造函数创建的function对象。function对象包含一个字符串,字符串包含函数的javascript代码。代码怎么可能是字符串?对于javascript来说,这很平常。数据和代码之间的区别是很模糊的。
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
因此,回调本质上是一种设计模式,并且jQuery(包括其他框架)的设计原则遵循了这个模式。
在JavaScript中,回调函数具体的定义为:函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行函数A。我们就说函数A叫做回调函数。如果没有名称(函数表达式),就叫做匿名回调函数。
因此callback 不一定用于异步,一般同步(阻塞)的场景下也经常用到回调,比如要求执行某些操作后执行回调函数。