js的回调函数理解及个别使用场景

1、概念

  • 在js中,不限制入参类型

  • 函数类型的入参就被称之为回调函数

  • 在定义函数时,回调函数一般被放在最后一个参数,但不强制

  • 官方说法:CALLBACK,即回调函数,是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

2、代码示例

①、最简单回调函数

function addPrintResult(a,b,printResult){
    let result = a + b;
    printResult(result);
}
function printResult(result){
    console.log(result);
}
addPrintResult(1,2,printResult);
运行结果:
3

②、匿名式回调函数

function addPrintResult(a,b,callback){
    let result = a + b;
    callback(result);
}
addPrintResult(1,2,function (result) {
    console.log(result);
});
运行结果:
3
用法解析(重要):
  • 定义addPrintResult函数时,共声明了3个入参,a,b,callback,此时js并不知道哪个是回调函数,因为js变量不是强类型的,只有代码编写者自己知道

  • 无论如何,反正在实际代码中,第三个参数-callback直接当做 function 来使了!

  • 而且,callback这个入参,在实际调用中,真的是个函数, 只不过是没有自己的名字而已,单纯一个函数对象

  • 函数,也是个对象,function(){} 和 {name:'wugb'},没什么区别

  • 最终,这个匿名函数对象在addPrintResult方法内被赋值给了callback变量,然后callback执行成功

  • 在js解释器中的代码应当如下:

let result = a + b;
callback = function (result) {
    console.log(result);
}
callback(result);
​
运行结果:
3
  • 匿名回调函数应当用到了 var 变量名 = function(){};的类似用法

3、回调函数需注意点

①、要确保实参一定是函数!

function addPrintResult(a,b,callback){
    let result = a + b;
    callback(result);
}
addPrintResult(1,2,'第三个参数');
运行结果:
TypeError: callback is not a function
  1. 瞎鸡儿填写实参,代码运行时肯定报错

②、方法内检验回调函数参数类型!

function addPrintResult(a,b,callback){
    let result = a + b;
    if(typeof(callback) == "function"){
        callback(result);
    }else{
        console.log('callback 就TM不是个函数,没法回调。')
    }
}
addPrintResult(1,2,'第三个参数');
运行结果:
callback 就TM不是个函数,没法回调。

4、和java中的区别

  • 直接将函数对象当成实参的用法,java中没有

  • java调用方法时,只能传递A方法的返回值给B方法,而不能将A方法体作为实参传给B方法

  • 如果需要A方法调用B,那么写法都是这个样子

function addPrintResult(a,b){
    let result = a + b;
    callback(result);
}
function callback(result){
    console.log(result);
}
addPrintResult(1,2);
  • 不太清楚新的lambda语法可不可以,后面再补充

  • java是强类型语言,就算有回调函数,估计也得是这种类型(伪代码)

function addPrintResult(int a,int b,function callback){
    let result = a + b;
    callback(result);
}
addPrintResult(1,2,'第三个参数');//写的时候直接报错,因为第三个参数不是function类型
  • 是不是TypeScript就有上面这种类似写法了?学ts的时候回头再补充这块

5、回调函数的应用场景

①、ajax异步通讯结果的处理

funtion ajaxReq(url,callback){
    let retData = req(url);
    callback(retData);
}

②、连续两次ajax请求(重要)

  • ajax一般是异步请求,所以不能同步获取到第一次请求的响应数据

  • 下面的代码不考虑同步响应的场景

  • 第二次ajax请求需要用到第一次ajax返回结果的场景

    funtion ajaxReq(url,callback){
        let retData = req(url);
        callback(retData);
    }
    funtion firstReqFunc(url1){
        ajaxReq(url1,function(retData){
            let firstRetData = retData;
            console.log('第一次请求获取到了结果!'+firstRetData);
        })
    }
    funtion secondReqFunc(firstRetData,url2){
        ajaxReq(url2,function(retData){
            let secondRetData = retData;
            console.log('第二次请求获取到了结果!'+secondRetData);
            dealWithData(firstRetData,secondRetData);
        })
    }
    ​
    ​
    ​
    ​

    调用1:

    注意!!直接这么写,必不可以,因为是异步方法

    let firstRetData = firstReqFunc(url1);//此时firstRetData是拿不到数据的
    secondReqFunc(firstRetData,url2);

改造后:

//第一步:改造firstReqFunc方法,给它加个入参,类型为回调函数
funtion firstReqFunc(url1,callback){
    ajaxReq(url1,function(retData){
        let firstRetData = retData;
        console.log('第一次请求获取到了结果!'+firstRetData);
        if(callback){
            callback(firstRetData);//回调函数中是肯定能拿到第一次请求返回值的,并且该回调函数会被调用
        }
    })
}
​
//第二步:在回调函数中调用第二个请求方法
function getFirstDataAndReqSecondReq(firstData){
    secondReqFunc(firstData,url2);
}
​
//实际用法为:
firstReqFunc(url1,getFirstDataAndReqSecondReq);
/*
    1、第一次请求获取到了结果
    2、将结果传递给了回调函数
    3、回调函数被调用时有了值,然后去调用第二次请求
*/

6、为什么要用回调函数

  • 因为灵活

  • 大大降低代码耦合

  • 以连续两次ajax请求为例,如果不用回调函数,想要第二次请求时就有第一次请求结果,那就只这么做

    • 在第一次请求方法的ajax回调函数中直接调用第二次请求方法

  • 如果第一次请求方法很多地方都在用,而第二次请求方法只在其中一个场景下用到呢?直接写死岂不是会影响到其它场景

  • 而且直接写死的话,维护及其困难,如果新场景是第一次请求后,把响应数据交给第三次请求方法使用呢?又得改老代码,而用到回调函数的话,只需要定义新的回调函数就行了,不影响之前的

  • 综上所述:要在合适的地方,尽量灵活使用回调函数

7、其它使用场景

以后每有用到的地方再补充吧,感觉应该有很多地方可以用到

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值