常常在setTimeout或者ajax中产生异步代码执行,执行的是回调函数,那么回调函数怎么写呢?这要跟回调函数的函数体内写法有关;
- 回调函数的函数体内return返回值不是函数;
- 回调函数的函数体内return返回值是函数;
分析一下代码的执行过程:
function callback () {
console.log('执行callback函数')
return function () {
console.log('我是callback函数的返回值');
}
}
function result() {
console.log( a );
}
var a = 0;
setTimeout(result, 200); // 1
setTimeout(callback, 200); // 执行callback函数
setTimeout(callback(), 200); // 执行callback函数 我是callback函数的返回值
a++;
setTimeout启动定时器,当达到预定时间时,宿主环境的事件循环机制将回调函数放入JS引擎的任务队列中执行或者等待执行;那么在setTimeout中如何书写回调函数呢?这里要根据回调函数的返回值来看:
- 回调函数的函数体内return返回值不是函数;
如果是这种情况,回调函数写清楚函数名,如果有参数,后面加(arg)带上arg参数即可; - 回调函数的函数体内return返回值是函数;
如果返回值是函数,回调函数写函数名,则只执行回调函数,函数名后加()则除了执行回调函数,也会执行回调函数返回的函数,不管(arg)是否为了传递参数,作为返回值的函数也会执行;这里还有个重要机制,函数名后加()代表函数调用,因此,回调函数会同步被调用,作为返回值的函数会异步调用;因此,如果把上文代码这样写:
setTimeout(callback(), 2000); // 执行callback函数(立刻输出) 我是callback函数的返回值(2秒后输出)
所以,在用回调函数时要注意,写回调函数名,或者加()带参数时,判断回调函数是否返回值是函数,这一点很关键。总之,函数名后加()就会被同步调用,因此要想异步调用,要避免加();如果带参数异步调用,则要将调用的函数A封装在另一个函数B中,函数A作为函数B的返回值,这样来带参数异步调用函数A。