一. 什么是回调函数?
被作为实参传入另一函数,并在该外部函数内被调用,用以来完成某些任务的函数,称为回调函数。
function f1(fn) {
let a =1;
console.log(a,'a')
fn()
}
f1(function() {
console.log('callback') // 1,'a' callback
})
和普通传参不同的是,回调函数作为实参在一个函数中传递并调用
二. 回调函数的特性
引用调用
调用的位置可以在作为实参传递的那个函数里面,即形参调用。也可以在实参里面调用,无论调用方式如何,引用调用的形参和实参调用是保持一致的。类似于引用数据类型的传参和更改。
形参调用
如上述代码,fn为形参。function() {
console.log(‘callback’)
} 为实参,当fn()形参调用时,实参unction() {
console.log(‘callback’)
}同样也会触发调用
实参调用
实参调用一般存在于回调函数嵌套中,例如
function f1(fn) {
let a =1;
console.log(a,'a')
fn((delay) => {console.log(delay,'delay')})
}
f1(function(fn) {
fn(111)
})
两者之间的关系
其实,形参和实参的调用概念引用只是为了便于理解,归根结底还是形参的调用,只是参考点不同,例如fn(111)对于f1来讲是实参调用,而对于function(fn){}函数来讲,还是作为形参去调用的。
所以,可以不用纠结于形参或者实参调用,我们只要明白引用调用相互影响这层关系即可。
三. 回调函数有什么作用?
其实,之前写的 手写ES6数组常用方法系列就有用到回调函数,例如可以参考手写ES6数组常用方法(every,some,sort,includes)。
好处主要有两点,
(1)可以在执行一个函数的同时执行另一个函数,且因为另一个函数是作为实参传递,另一个函数是可以自定义的;
(2)除了主函数可以处理数据外,回调函数也可以进一步处理数据,并返回想要的结果。
例如Vue升级后的Vue3.x就有大量的回调函数应用场景,可见回调函数对于方法的集成是很有帮助的。
例如watch(侦听器),我们可以利回调函数做个简单的示意
function watch(userCount, fn) {
// to do soming to format
let foramtValue = userCount + 1
fn && fn(foramtValue)
}
watch(100, (val) => {
console.log(val,'val')
})