前端面试中最容易被问到的问题就是什么是回调函数?回调函数的意义?通过本文咱们彻底搞懂什么是回调函数。
1.什么是回调函数?
最通俗的解释就是:回调函数就是把这个函数当做参数传给另一个函数,在另一个函数里面通过这个函数参数去调用这个函数,这个过程称为回调。而那个当成参数的函数就是回调函数。
看下面代码:
//另一个函数
function test(callback){
console.log('test() start....')
callback(); //这里是回调
console.log('test() end....');
}
//定义回调函数
function fn(){
console.log('我是回调函数...')
}
test(fn);
运行结果:
test() start....
我是回调函数...
test() end....
这里fn函数就是回调函数。之所以称为回调函数,是因为在另一个函数中调用完回调函数后会立刻返回主函数(这里的主函数就是test函数)继续执行,所以很形象的称之为回调函数,英文名字:callback.
注意:执行回调函数后是立即返回,这里的立即返回就是不会等待回调函数的执行结果,立刻返回主函数执行后面的代码。
把上面的代码改写如下:
function test(callback){
console.log('test() start....')
callback();
console.log('test() end....');
}
function fn(){
setTimeout(()=>console.log('我是回调函数...'),1000)
}
test(fn);
运行结果:
test() start....
test() end....
我是回调函数...
因为setTimeout本身就是异步操作。所以在调用完回调函数后,会立刻执行完主函数的代码。
其实setTimeout本身就执行了回调函数,可以说setTimeout是各位小伙伴最早接触的回调函数了,我们看看setTimeout的定义。
setTimeout(callback, delay)
到此,关于回调函数的概念咱们总结以下两点:
1). 回调函数一定是把自己当做参数传递给另一个函数,在另一个函数中调用。如果单独调用这个函数那么它就不是回调函数。
2). 回调函数调用后会立刻返回执行主函数的代码,不会等待回调函数的执行结果。
2.回调函数的意义?
好奇的小伙伴肯定会问: 我们为什么不直接在test函数中,直接调用fn()方法呢?为啥非要把fn当做参数传递给test然后在test中调用呢?
上面的代码改写如下:
function test(){
console.log('test() start....')
fn();
console.log('test() end....');
}
function fn(){
setTimeout(()=>console.log('我是回调函数...'),1000)
}
test(fn);
运行结果:
test() start....
test() end....
我是回调函数...
既然运行结果完全一样,咱们使用回调函数的意义是什么呢?
回调函数的意义在于:通常test函数我们可以理解为是系统内部的代码,换句话说就是系统开发定义好的,咱们程序员看不到这段代码,也不允许你修改这段代码。但是系统内部又想提供一种机制允许执行外部用户自己写的代码,那么就可以使用回调函数。这样做的好处是:通过回调函数用户的程序逻辑可以传递给系统内部,系统内部调用完回调函数,还可以把结果反馈给用户程序。
3.回调函数传递参数
主函数在执行回调函数时,可以传参,这个回调函数就可以获得主函数传递过来的参数值。
function test(callback){
console.log('test() start....')
fn('你好回调函数...');
console.log('test() end....');
}
function fn(resp){
console.log(resp);
}
test(fn);
运行结果:
test() start....
你好回调函数...
test() end....
上面的例子是主函数给回调函数传参,当然回调函数也可以给主函数传参。
function test(callback,resp){
console.log('test() start....')
console.log(resp)
fn('你好回调函数...');
console.log('test() end....');
}
function fn(resp){
console.log(resp);
}
test(fn,'helloworld');
运行结果:
test() start....
helloworld
你好回调函数...
test() end....
回调函数传参另一个重要意义在于,如果主函数中执行一些异步操作,我们如何把这个异步操作的结果返回呢?看下面代码:
function test(){
setTimeout(()=>{
return{
username: 'zhangsan'
}
},2000)
}
let resp = test();
console.log(resp);
运行结果:
undefined
因为在我们调用完test()后就已经获得函数的返回值了,两秒钟后再返回已经不赶趟了,这就很尴尬了。 这时候回调函数就派上用场了。
function test(callback){
setTimeout(()=>{
callback({username: 'zhangsan'})
},2000)
}
function fn(resp){
console.log(resp);
}
test(fn);
运行结果:
{ username: 'zhangsan' }
4.Java语言能实现回调函数吗?
回调函数是一种编程思想,与语言无关;回调函数的核心就是将函数的指针(或者引用)传递给其他函数,让其他函数在特定的时候,通过指针(或者引用)调用该回调函数。
以下是Java实现回调的例子。
//函数式接口用来创建函数引用。
interface Callback {
void success();
}
class FutureCallback implements Callback {
@Override
public void success() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("do success");
}
}
public class CallabackDemo {
private Callback callback;
public CallabackDemo(Callback callback) {
this.callback = callback;
}
public void doSomething(){
System.out.println("do something start...");
new Thread(() -> callback.success()).start();
System.out.println("do something end...");
}
public static void main(String[] args) {
Callback callback = new FutureCallback();
new CallabackDemo(callback).doSomething();
}
}
运行结果:
do something start...
do something end...
do success
小结:
1).回调函数就是把这个函数当做参数传给另一个函数,在另一个函数里面通过这个函数参数去调用这个函数,那么当成参数的函数就是回调函数。 2).回调函数的意义是允许系统内部代码通过回调函数执行用户代码。 3).通过回调函数可以获得一个异步操作的返回值。