专栏首页亦枫的大佬之路JavaScript中的回调函数(callback)

JavaScript中的回调函数(callback)

什么是回调函数

被作为实参传入另一函数,并在该外部函数内被调用,用以来完成某些任务的函数,称为回调函数。

在JavaScrip中,function是内置的类对象,也就是说它是一种类型的对象,可以和其它String、Array、Number、Object类的对象一样用于内置对象的管理。因为function实际上是一种对象,它可以“存储在变量中,通过参数传递给(另一个)函数(function),在函数内部创建,从函数中返回结果值”。

因为function是内置对象,我们可以将它作为参数传递给另一个函数,延迟到函数中执行,甚至执行后将它返回。这是在JavaScript中使用回调函数的精髓。

回调函数被认为是一种高级函数,一种被作为参数传递给另一个函数(在这称作"otherFunction")的高级函数,回调函数会在otherFunction内被调用(或执行)。回调函数的本质是一种模式(一种解决常见问题的模式),因此回调函数也被称为回调模式。

示例

同步回调函数:

function greeting(name) {
  alert('Hello ' + name);
}

function processUserInput(callback) {
  var name = prompt('请输入你的名字。');
  callback(name);
}

processUserInput(greeting);

异步回调函数:

    function ff(a, b, cbk) {
        setTimeout(() => {
            cbk(a + b);
        }, 3000);
    }
    function f(callback) {
        var x = 3, y = 4;
        var z = 0;
        callback(x, y, function (re) {
            z = re;
            console.log(z)
        });
        console.log("主函数")
        return z;
    }
    f(ff);

点击回调函数:

function testFun(event, str) {
	console.log(str);
}
 
var test = document.getElementById('test');
test.addEventListener('click', function(event) {
	testFun(event, 'this is a test');
});

对比来看,回调与同步、异步并没有直接的联系,回调只是一种实现方式,既可以有同步回调,也可以有异步回调,还可以有事件处理回调和延迟函数回调,这些在我们工作中有很多的使用场景。

我们可以像使用变量一样使用函数,作为另一个函数的参数,在另一个函数中作为返回结果,在另一个函数中调用它。当我们作为参数传递一个回调函数给另一个函数时,我们只传递了这个函数的定义,并没有在参数中执行它。

当包含(调用)函数拥有了在参数中定义的回调函数后,它可以在任何时候调用(也就是回调)它。

这说明回调函数并不是立即执行,而是在包含函数的函数体内指定的位置“回调”它(形如其名)。

回调函数是闭包的。

当作为参数传递一个回调函数给另一个函数时,回调函数将在包含函数函数体内的某个位置被执行,就像回调函数在包含函数的函数体内定义一样。闭包函数可以访问包含函数的作用域,所以,回调函数可以访问包含函数的变量,甚至是全局变量。

为什么使用回调函数

我们都知道js是单线程的,这种设计模式给我们带来了很多的方便之处,我们不需要考虑各个线程之间的通信,也不需要写很多烧脑的代码,也就是说js的引擎只能一件一件事的去完成和执行相关的操作,所以所有需要执行的事情都像排队一样,等待着被触发和执行。

可是如果这样的话,如果在队列中有一件事情需要花费很多的时间,那么后面的任务都将处于一种等待状态,有时甚至会出现浏览器假死现象,例如其中有一件正在执行的一个任务是一个死循环,那么会导致后续其他的任务无法正常执行,所以js在同步机制的缺陷下设计出了异步模式。

在异步执行的模式下,每一个异步的任务都有其自己一个或着多个回调函数,这样当前在执行的异步任务执行完之后,不会马上执行事件队列中的下一项任务,而是执行它的回调函数,而下一项任务也不会等当前这个回调函数执行完,因为它也不能确定当前的回调合适执行完毕,只要引它被触发就会执行。

回调函数什么时候执行

回调函数,一般在同步情境下是最后执行的,而在异步情境下有可能不执行,因为事件没有被触发或者条件不满足。

回调函数的传参

1.将回调函数的参数作为与回调函数同等级的参数进行传递:

2.回调函数的参数在调用回调函数内部创建:

什么时候用回调函数

1.资源加载:动态加载js文件后执行回调,加载iframe后执行回调,ajax操作回调,图片加载完成执行回调,AJAX等等。

2.事件:DOM事件及Node.js事件基于回调机制 (Node.js回调可能会出现多层回调嵌套的问题)。

3.setTimeout的延迟时间为0,这个hack经常被用到,settimeout调用的函数其实就是一个callback的体现

4.链式调用:链式调用的时候,在赋值器(setter)方法中(或者本身没有返回值的方法中)很容易实现链式调用,而取值器(getter)相对来说不好实现链式调用,因为你需要取值器返回你需要的数据而不是this指针,如果要实现链式方法,可以用回调函数来实现。

5.setTimeout、setInterval的函数调用得到其返回值。由于两个函数都是异步的,即:他们的调用时序和程序的主流程是相对独立的,所以没有办法在主体里面等待它们的返回值,它们被打开的时候程序也不会停下来等待,否则也就失去了setTimeout及setInterval的意义了,所以用return已经没有意义,只能使用callback。【不太理解】callback的意义在于将timer执行的结果通知给代理函数进行及时处理。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JavaScript进阶之路系列(一): 高阶函数

    看了这篇文章,你就会高阶函数了,是不是听起来很牛?高阶函数,听起来很高级,其实是很接地气,大家经常会用到的东西,比如filter,map,回调函数。

    刘亦枫
  • JavaScript中的函数防抖与函数节流

    函数防抖(debounce)当调用动作过n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间。

    刘亦枫
  • JavaScript中的闭包(closure)

    在JavaScript中,当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包。简单说,闭包就是能够读取其他函数内部变量的函数。

    刘亦枫
  • js 立即执行函数

    通常,全局变量被作为一个参数传递给立即执行参数,这样它在函数内部不使用window也可以被访问到。

    星辉
  • Python学习(五)---- 不可不知的装饰器!

    https://blog.csdn.net/fgf00/article/details/52061971

    智能算法
  • 【译】JS的执行上下文和环境栈是什么?

    这篇文章中,我将深入探讨JavaScript中的一个最基本的部分,即执行上下文(或称环境)。读过本文后,你将更加清楚地了解到解释器尝试做什么,为什么在声明某些函...

    嘉明
  • 前端入门18-JavaScript进阶之作用域链声明正文-作用域链

    作为一个前端小白,入门跟着这几个来源学习,感谢作者的分享,在其基础上,通过自己的理解,梳理出的知识点,或许有遗漏,或许有些理解是错误的,如有发现,欢迎指点下。

    请叫我大苏
  • YxtCMF后台的注入和getshell分析

    说明: 这摊源码是基于thinkphp3.2.3开发的,然后有几个重要的目录记录一下:

    字节脉搏实验室
  • Kotlin 重构 - F6 not working?原始代码目标代码重构步骤如下:小结问题

    Option + Enter, Convert member to extension

    lambeta
  • 机器学习第4天:线性回归及梯度下降

    线性回归属于监督学习,因此方法和监督学习应该是一样的,先给定一个训练集,根据这个训练集学习出一个线性函数,然后测试这个函数训练的好不好(即此函数是否足够拟合训练...

    明天依旧可好

扫码关注云+社区

领取腾讯云代金券