回调函数 桃扇骨 2021-11-13 21:28 533阅读 0赞 作为JS的核心,回调函数和异步执行是紧密相关的,也是必须跨过去的一道个门槛。 那么究竟什么是回调函数(Callback),其实回调函数并不复杂,明白两个重点即可: 1. 函数可以作为一个参数在另一个函数中被调用。 2. JS是异步编程语言,这就是说JS代码的执行顺序并不是从上至下按部就班完成的。大多数语言都是同步编程语言,比如现在我们有3行代码,那么系统一定是一行一行按顺序向下执行的,第一行执行完了,执行第二行,紧跟着最后执行第三行,你可能会说这不是废话吗?且慢,在JS里则不尽然,比如有3行代码,并不是排在最前面的代码就是最先执行完毕的,很有可能是最后一行语句最先执行完,然后排在最前面的那行反而是最后执行完毕的,所以我们说JS是异步编程语言。 下面以node.js为例,举一个例子保证你在3步之内搞清楚究竟什么叫回调函数: ## **STEP 1:** ## var fs = require( "fs"); var c function f(x) { console.log(x) } function writeFile() { fs.writeFile( 'input.txt', '我是通过fs.writeFile 写入文件的内容', function (err) { if (!err) { console.log( "文件写入完毕!") c = 1 } }); } c = 0 writeFile() f(c) 以上代码不难理解,就是设置一个全局变量c = 0,然后执行writeFile函数(也就是写入一个文件input.txt),这个函数里面有一行c = 1,函数执行完毕之后再跳出来调用f()函数,f()函数很简单,就是把打印一个变量,仅此而已。 按照 **“正常”** 逻辑,首先c=0,然后调用writeFile函数,该函数里面有一句c = 1,最后再调用f(c),又因为调用writeFile()是在f(c)之前,所以c=1这条语句肯定是会被执行到,那么结果应该是打印1,但是万万想不到,结果竟然是0,明明我们在writeFile函数里我们重新对c进行了赋值,为什么结果还是0呢? 因为程序运行到writeFile()这一行的时候,是一个比较耗时的IO操作,JS碰到这种操作并不会停在原地一直等待直到函数执行完毕,而是直接运行下一条代码(即f(c)),而此时 c = 1这一行代码其实并没有被执行到,所以打印出来的结果还是0 ! 那你肯定会说,要解决这个问题还不容易,我们把调用f(c)也放进writeFile函数里面不就行了呗!这样就能保证c = 1之后再调用f(c)了吧?没错,就这么简单: ## **STEP 2:** ## var fs = require( "fs"); var c function f(x) { console.log(x) } function writeFile() { fs.writeFile( 'input.txt', '我是通过fs.writeFile 写入文件的内容', function (err) { if (!err) { console.log( "文件写入完毕!") c = 1 f(c) } }); } c = 0 writeFile() 这个代码的逻辑不需要多说了吧,因为实在太简单了,就是把f(c)放进了writeFile()里面,那么c=1必然会被执行到,然后才执行f(c),不用多说,结果肯定是显示为1。但是改成这样并不完美,因为这么做就相当于将f()"焊死"在writeFile()里了,如果此处我最终想调用的函数不是f()而是别的其他函数咋整?难不成要写几个不同的writeFile(),而他们之间的区别仅仅是最后调用的那个函数不同?这样也太笨了吧,于是今天的主角:关键字**callback**登场了。 ## **STEP 3:** ## var fs = require( "fs"); function f(x) { console.log(x) } function writeFile(callback) { //关键字callback,表示这个参数不是一个普通变量,而是一个函数 fs.writeFile( 'input.txt', '我是通过fs.writeFile 写入文件的内容', function (err) { if (!err) { console.log( "文件写入完毕!") c = 1 callback(c) // 因为我们传进来的函数名是f(),所以此行相当于调用一次f(c) } }); } var c = 0 writeFile(f) // 函数f作为一个参数传进writeFile函数 经过改造后的代码出现了两次callback关键字,第一个callback出现在writeFile的形参里,起定义的作用,表示这个参数并不是一个普通变量,而是一个函数,也就是前面所说的重点1,即所谓的“以函数为参数”。 第二个callback出现在c = 1下面,表示此处“执行”从形参传递进来的那个函数。这样一来,writeFile()函数在执行完毕之后到底调用哪个函数就变“活”了,如果我们想writeFile()函数执行完之后并不是像第二个例子那样只能调用f(),而是还有别的函数比如说x() y() z(),那么只需要写成 writeFile(x),writeFile(y)... 就行了。 我相信你已经看明白上面的代码,因为实在并不高深,那么我们现在开始用一句话攻略做一个总结: **在大多数编程语言中,函数的形参总是由外往内向函数体传递参数,****但在JS里如果形参是关键字"callback"则完全相反,****它表示函数体在完成某种操作后由内向外调用某个外部函数。** 有时候,我们会看到一些函数的形参列表里又出现一个函数定义的情况,初时感觉一头雾水,其实只要你了解了上面的内容,看这种直接在函数调用的时候嵌入一个function的写法会很简单,其本质上仍然是回调函数,因为没有了函数名,所以也称**匿名函数。** 如本例如果要写成这种风格的话就是长成这样了: var fs = require( "fs"); function writeFile(callback) { fs.writeFile( 'input.txt', '我是通过fs.writeFile 写入文件的内容', function (err) { if (!err) { console.log( "文件写入完毕!") c = 1 callback(c) } }); } var c = 0 writeFile( function (x) { console.log(x) }) writeFile()函数不变,只是在调用它的时候,直接将函数体嵌在形参列表里,其作用跟上一个例子完全一样。其实在本例中,fs.writeFile函数后面也跟了一个匿名回调函数 function (err) \{\},这个函数表示当文件写入完毕后,就回调它,如果在写入过程中出现了错误,则通过变量err携带出来。我相信有了前面的铺垫,您已经肯定能理解它的含义了,事实上这种写法在JS里是最常见的主流风格。 **【补充】**在JS里,当然也并非所有操作都是异步的,比如for循环,无论这个for循环需要耗时多长,系统也一定会等它转完之后才会执行下面的语句,这一点跟其他大部分同步语言是一致的。我所了解的会产生异步执行的操作大概有以下几种: 定时器、建立网络连接、读取网络流数据、向文件写入数据、Ajax提交、请求数据库服务,等等。 如果至此你还是没弄清楚到底什么是回调函数,那么绝不是您的问题,而一定是我的表达有不足之处,欢迎留言探讨! ![æå°±æ¯ççä¸è¡åï¼ç«åªï¼][006m97Kgly1g3lkdlc8lqj30hs0g3mzu.jpg] [006m97Kgly1g3lkdlc8lqj30hs0g3mzu.jpg]: /images/20211113/ccf620a1be15499aac3fdaa3468fa7d1.png
相关 回调函数 作者:桥头堡 链接:http://www.zhihu.com/question/19801131/answer/27459821 来源:知乎 著作权归作者所有,转载 清疚/ 2022年09月24日 11:26/ 0 赞/ 34 阅读
相关 回调函数 一、回调函数 我们经常在C++设计时通过使用回调函数可以使有些应用(如定时器事件回调处理、用回调函数记录某操作进度等)变得非常方便和符合逻辑,那么它的内在机制如何呢,怎么定义 ╰+攻爆jí腚メ/ 2022年06月16日 23:37/ 0 赞/ 292 阅读
相关 回调函数 回调函数是一种函数指针的使用方式。 stdcall和cdecl的区别:这个问题涉及到函数调用的汇编知识,暂只需记住stdcall和cdecl的参数压栈顺序是相同的,参 傷城~/ 2022年06月12日 07:21/ 0 赞/ 303 阅读
相关 回调函数 作者:no.body 链接:https://www.zhihu.com/question/19801131/answer/27459821 来源:知乎 著作权归作者 ╰半夏微凉°/ 2022年06月11日 05:37/ 0 赞/ 58 阅读
相关 回调函数 转自: 回调函数 在看LWIP时,见到用回调函数,再看某老外公司OPC源代码时,见到用回调函数。看我国内某些代码( 朴灿烈づ我的快乐病毒、/ 2022年06月11日 05:36/ 0 赞/ 270 阅读
相关 回调函数 回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实 青旅半醒/ 2022年06月02日 20:51/ 0 赞/ 306 阅读
相关 回调函数 转载自[https://zhidao.baidu.com/question/572699725.html][https_zhidao.baidu.com_question_57 水深无声/ 2021年12月12日 04:01/ 0 赞/ 481 阅读
相关 回调函数 作为JS的核心,回调函数和异步执行是紧密相关的,也是必须跨过去的一道个门槛。 那么究竟什么是回调函数(Callback),其实回调函数并不复杂,明白两个重点即可: 1. 函 桃扇骨/ 2021年11月13日 21:28/ 0 赞/ 534 阅读
相关 回调函数 一、定义 什么是回调函数?它首先是一个函数,这是肯定的,我举个例子:有两个函数A和B,首先应用程序将A的地址告诉B,这称之为注册回调函数,B在收到外部某个命令的时候,可以根据 客官°小女子只卖身不卖艺/ 2021年09月30日 11:56/ 0 赞/ 573 阅读
相关 回调与回调函数 回调与回调函数 回调 回调函数 回调 回调指的是某函数在执行的时候,由于某些原因,该函数被迫中止执行,交出当前线程的使用权,当前线程转而执行其它函 悠悠/ 2021年09月25日 04:26/ 0 赞/ 564 阅读
还没有评论,来说两句吧...