V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
feigle
V2EX  ›  JavaScript

js 中经常会用到回调函数,为什么叫回调函数呢?

  •  
  •   feigle · 2019-12-20 14:59:48 +08:00 · 7024 次点击
    这是一个创建于 1792 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如下面的代码:

    function a(callback){
    
        var m = 1;
        var n = 2;
        alert(callback(m,n));
    }
    
    function b(m,n){
    
        return m+n;
    }
    
    a(b);
    

    程序运行到 a(b);时,不是执行 a 函数吗,然后 a 函数体中调用了 b 函数。 有人说,回调函数,是当父函数执行完后再去执行传入的函数,感觉不能理解。

    35 条回复    2019-12-22 16:11:38 +08:00
    jeodeng
        1
    jeodeng  
       2019-12-20 15:03:43 +08:00
    function a(callback) {
    console.log(1);
    callback();
    console.log(2);
    }

    function b() {
    console.log('callback');
    }

    a(b)

    输出 1 callback 2,我不认为是 a 执行完以后再去执行 b
    manami
        2
    manami  
       2019-12-20 15:05:55 +08:00 via Android
    callback 翻译问题,就像 java 语言 robust—“鲁棒性”
    sunsai
        3
    sunsai  
       2019-12-20 15:07:01 +08:00   ❤️ 1
    把 b 函数调用的控制权交给了 a, a 可以调用也可以不调用, 具体什么时候调用, 调用几次, 都不是 b 自己可以控制的
    Sapp
        4
    Sapp  
       2019-12-20 15:13:52 +08:00
    根本不是一码事,你写的是回调函数,但你这是最基础定义的回调函数,而你后面那个有人说的,是通常意义上的异步回调函数,实际哪怕是异步也说错了,只是在很多情况下,异步回调是会导致父函数的同步执行完了才调用它而已,但是这不代表所有的都是这样,这只是一个结果,但是不是定义。
    一般的回调函数是指传入的到了某个特定的时候调用的函数,这个可能是一个异步也可能是同步,这个特定的时候可能是指这个函数整体执行完毕,也可能是这个函数某一部分执行完毕
    JerryCha
        5
    JerryCha  
       2019-12-20 15:19:59 +08:00
    和事件机制有点关系,这个需要踩了坑才能理解为什么是这样
    ![[email protected]]( https://i.loli.net/2019/12/20/jqVF8txmSvwHn9l.png)
    yumc
        6
    yumc  
       2019-12-20 15:30:02 +08:00
    我不懂但是我说一下我的理解:
    回调函数和其他面向对象语言的接口回调相似,方法 a 已经实现具体的功能,但是在方法 a 内部某些地方会调用 b 方法,b 方法没有被实现,依赖于外部实现。
    eason1874
        7
    eason1874  
       2019-12-20 15:35:32 +08:00   ❤️ 1
    有函数的语言就有回调函数,通过传参给另一个函数去调用的函数就叫回调函数。有同步回调,也有异步回调,不同语言的回调形式可能有所不同。

    同步回调的就是通过参数给你的(函数)代码过程再插入一段代码(回调函数),回调函数的功能一般是 filter (处理部分数据)或者 action (增加一个动作)。

    异步回调大多是因为执行函数本身就是异步,非阻塞,不等结果返回,你在代码过程不能获得函数执行结果,所以就只能通过异步回调,先传参,等函数执行完了函数再根据参数调用你要执行的处理函数,把结果传给它。
    will0404
        8
    will0404  
       2019-12-20 15:36:23 +08:00
    新手容易在各种专有名词上纠结,没有必要太较真。

    a 的参数是个函数,如此而已。当这个参数命名为 callback 时,它多半是在告诉调用它的人,我会在某个时刻调用它,一般在我先去做一些别的事之后。因此 callback 这个命名往往出现在异步函数定义中,这是种默契,而非官方约定。
    huijiewei
        9
    huijiewei  
       2019-12-20 15:40:08 +08:00
    callback 只是一个命名约定
    learnshare
        10
    learnshare  
       2019-12-20 15:40:23 +08:00
    你的代码在演示闭包,也算是一种回调

    回调在现实生活中比较好解释:
    师傅修车的时候,喊徒弟 [拿个螺丝刀] ,这是回调的前提,可能的结果有以下几种
    1. 同步成功:徒弟 [直接递上螺丝刀]
    2. 同步失败:徒弟说 [螺丝刀在你手里]
    3. 异步成功:徒弟找了一圈, [拿来了螺丝刀]
    4. 没有回调:徒弟装作没听见
    azcvcza
        11
    azcvcza  
       2019-12-20 15:41:07 +08:00
    程序这东西,解释专有名词很费劲,但是写起来也就那样把。
    kop1989
        12
    kop1989  
       2019-12-20 15:43:31 +08:00
    回调函数( callback )其实是一种通用约定,用于描述将函数调用权交给其他(人、线程、进程、接口等)未知第三方的一种做法。lz 举的例子是最简单的一种实现方式,但不限于此。
    只要是把触发、调用权交给对方的,都叫回调函数。
    qiayue
        13
    qiayue  
       2019-12-20 15:46:52 +08:00
    举一个真实例子,用户微信支付完成后,微信支付服务器调用你的接口,告诉你支付数据,这也叫做回调。
    回头再调的意思。
    enjoyCoding
        14
    enjoyCoding  
       2019-12-20 15:48:40 +08:00
    普遍意义上我们嘴中的回调是要有异步操作的,异步操作之后触发的函数就被叫做回调函数.
    sixway
        15
    sixway  
       2019-12-20 15:50:19 +08:00
    可以说是异步操作
    wangxiaoaer
        16
    wangxiaoaer  
       2019-12-20 15:54:14 +08:00
    callback = call - back = 反过来 call =反过来调用 = 回调

    我觉得这个翻译听贴切的。

    回到你的例子:

    a(b) == 你调用 a (发起者是你)然后 a 调用 b()(发起者是 a ),从发起者的角度看是反过来了。
    wangyzj
        17
    wangyzj  
       2019-12-20 15:57:19 +08:00
    你写的是函数指针
    不是基于单线程事件的回调函数
    zenxds
        18
    zenxds  
       2019-12-20 15:59:13 +08:00
    你在淘宝买了个东西,东西到了快递打电话给你去取就是回调,这是一个异步的过程,难不成你下了单就一直卡着等吗
    hehheh
        19
    hehheh  
       2019-12-20 15:59:46 +08:00
    上过微机原理的课肯定听说过 interrupt,虽然不是一码事,可是是一个道理
    1KN6sAqR0a57no6s
        20
    1KN6sAqR0a57no6s  
       2019-12-20 16:12:58 +08:00   ❤️ 1
    1、“回调函数,是当父函数执行完后再去执行传入的函数。” 这句话是错误的,父函数并不是呆呆地执行每一个以参数形式传进来的回调函数,它有可能在适当的时机调用,也可能永远不调用。2、回调函数本质上是“面向未来编程”,当我开始做一件事的时候(父函数),有些伴生的事明明还没有发生(事件、条件),我已经想好了应对这些可能事件的方法(回调函数)。3、“面向未来编程”的通俗名字是异步编程,用回调函数的形式写代码只是异步编程的一种模板,你也可以用“监听事件 /触发事件”这样的模板来进行异步编程。
    chairuosen
        21
    chairuosen  
       2019-12-20 16:28:17 +08:00   ❤️ 1
    现在调用么?
    不,等我先弄别的,回头再调你
    lllllliu
        22
    lllllliu  
       2019-12-20 16:53:17 +08:00
    一切不考虑上下文的回调都不是好回调 (狗头
    feigle
        23
    feigle  
    OP
       2019-12-20 16:53:35 +08:00
    @chairuosen 最佩服这个解释啦。
    1、如果是现在调用你,那么就是直接 b(x,y),就够了,没必要在外面包一层
    2、如果在调用你之前,还要做点事,那么就是 a(b),在 a 里面做点事,然后在 a 中去调用 b。
    mahogany
        24
    mahogany  
       2019-12-20 17:34:33 +08:00
    一件事情 A 不一定做得完,需要 B 的参与. 但是 A 傻等着 B 完成他的工作也不是个办法,干脆 B 做完之后通知 A 继续做.
    这里需要从'单个逻辑控制流'的看法转变成 '多组件协作',当然这主要说的是异步回调.
    bigggge
        25
    bigggge  
       2019-12-20 18:24:04 +08:00
    Don't Call Me, I'll Call You
    v2student
        26
    v2student  
       2019-12-20 18:45:45 +08:00
    结果返“回”了
    再“调”用这个函数
    by73
        27
    by73  
       2019-12-20 18:49:35 +08:00
    其实这是翻译问题。原意很清楚,就是日常用语 I'll call back later,本意也一样,就是“我稍后会去调用它”。
    hoyixi
        28
    hoyixi  
       2019-12-20 18:59:24 +08:00
    本质是函数作为参数传递。至于啥时候调,是立刻调,还是稍后调, 随你的便。 所以翻译或者强调成回调函数,纯属脱裤子放屁,唯恐不够复杂。

    至于“稍后调”的场景,最好理解的是事件处理( event handler ),先定义好事件处理函数,事件一发生就调用。 如果你学到了 DOM,就非常容易理解了。
    ljpCN
        29
    ljpCN  
       2019-12-20 19:00:31 +08:00 via Android
    "把函数给我,我回头执行的时候得调用一下"
    ethego
        30
    ethego  
       2019-12-20 19:20:37 +08:00
    在完全并行化的 V8 里,曾经有很长一段时间回调是唯一控制两个函数顺序执行的方法,然后后来我们有了 future promise,以及 async await 这样更好的并发语义。
    Arrowing
        31
    Arrowing  
       2019-12-20 21:26:56 +08:00
    习惯性的理解吧,等于说完成了一件事,要告诉调用者,我已经完成了。
    原因是,js 里,是一个 Event Loop 模型,异步处理的任务,不会阻塞同步任务,异步处理完了,会将任务丢到正常的执行队列里,此刻一般会使用回调方法来通知。
    dangyuluo
        32
    dangyuluo  
       2019-12-21 05:32:13 +08:00
    你这个例子不能完美体现“回调”二字,换个想法

    ```
    element.onClick(doSomething)
    ```
    crella
        33
    crella  
       2019-12-21 11:54:23 +08:00
    不懂就问,这个和 函数 的 反射 有什么不同?
    crella
        34
    crella  
       2019-12-21 12:04:08 +08:00
    我暂时只能理解到这一步:

    https://paste.ubuntu.com/p/df99xRKDvB/
    dlqingxi
        35
    dlqingxi  
       2019-12-22 16:11:38 +08:00
    我给你写一段代码感受一下回调函数。
    var fun1 = function(){//具有某种功能的函数
    console.log('fun1 called');
    }
    var fun2 = function(){//具有某种功能的函数
    console.log('fun2 called);
    }

    class Something {
    callbackFun;//回调函数,注意这里是空,它在某个时机会被调用。现在也不知道到时候具体调哪个函数
    ctor(){
    }

    setCallback(callback, thisObj, myArgs){//合适的时候设置 回调函数
    this.callbackFun = callback.bind(thisObj, myArgs);
    }

    doCallback(){//真正执行回调函数
    this.callbackFun && this.callbackFun();
    }

    }

    回调回调,回来再调。
    做完了某个事情后,应该调用某个函数。
    此为由来。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5513 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 08:56 · PVG 16:56 · LAX 00:56 · JFK 03:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.