在百度百科中,回调函数的定义就是一个被作为参数传递的函数。
通俗地理解:我现在写一个函数,里面定义了函数A,那么函数A就是回调函数。
以前我认为JavaScript不过是一门在浏览器端执行的简单脚本语言,我只要会写会读就行了,正经写程序还是要靠C++\C#\Java等高级语言来做。看了回调函数和它的特点特别是看了一些JavaScript函数的原型才明白JavaScript虽然简单,可是这门语言设计得真是巧妙,深入掌握并不容易。
我的理解:回调函数就是定义了一定要(回来)执行的函数,至于什么时候执行、怎么执行、具体的执行内容是什么,解释器不用理会,到了要执行的时候,你把它放到执行队列里就行了。
回调函数是JavaScript的精华之一,它给JavaScript这门语言增添了很多的精巧和奥妙。
比如:
1、JavaScript作为一门编程语言本身只支持单线程,怎样支持多线程编程呢?
JavaScript操作的是BOM和DOM,为了避免处理冲突,作为编程语言它本身是单线程是可以理解的,但作为宿主的浏览器是支持多线程的,那么它就可以通过回调函数在浏览器的支持下实现多线程。
比如Jquery处理鼠标单击事件的定义是:$(selector).click(function)
这里的click(function)是回调函数,同样对于鼠标的单击事件有更广泛的定义:$(selector).on(event,childSelector,data,function)
这里的function也是回调函数,意思是说,这个函数是一定要执行的,具体什么时候执行不确定,当执行到这行代码的时候,浏览器就把函数的具体实现放到执行队列去排队执行就好了,这行代码就算过去了,浏览器可以继续执行下一行的代码了。
单线程容易造成阻塞,因为必须等一行代码执行完了才能继续执行下一行代码,如果某一行代码很耗时,那么给用户的感觉就是浏览器卡顿,而有了回调函数的这一执行机制,就有效地避免了这种拥塞,给用户的感觉就是多线程的执行环境,其实是浏览器的多线程和JavaScript的回调函数执行机制联合起了作用。
2、编程的函数实现了某些功能,可是这些函数的具体实际的应用依赖于某些特定的需求,这些需求我现在不清楚,怎样让函数去契合这些需求呢?
举例来说,数组排序很简单:
var arr=[92,12,29,24] arr=arr.sort() console.log(arr)
执行输出为:[12, 24, 29, 92]
默认的就是从小到大的升序排序,针对包含了数字的数组。
问题是数组也可能是字符串或者是时间,又或者我想要的是从大到小的排序呢?这些都是开始无法确定的。
看sort的函数说明:
method:sort(function):array
中间的参数是个(回调)函数,这为程序功能提供了更多的实现。
如果需要是降序排序:
var arr=[92,12,29,24] function compareNumber(a,b){ return b-a } arr=arr.sort(compareNumber) console.log(arr)
如果是字符串数组呢?现在有四个时间的字符串,我想按照月份从小到大排序:
arr=['20000901','20080401','20211105','20180103'] function compareMonthChar(a,b){ return Number(a.substr(4,2)) - Number(b.substr(4,2)) } arr=arr.sort(compareMonthChar) console.log(arr)
关键点还在于,回调函数作为参数只有函数名而没有参数列表,这一点的设计真是灵巧。想一想C语言中的指针的灵活使用和C#中委托就理解了这个设计的意图。
3、软件开发无非就是输入、处理、输出这些,有些函数实现了输入,具体的处理和输出需要未来的开发者去实现,怎样做到这一点呢?
比如在Node.js的Web应用开发中,获取了访问者的数据,他的连接和一些访问参数,怎样响应呢?
使用回调函数来衔接。
看Node.js中的函数设计:
var express = require('express') var app = express() app.get('/', function (req, res) { res.send('hello world') }) app.listen(3000)
这里的函数 function (req, res) { res.send('hello world') }就是回调函数。
const http=require('http') const fs=require('fs') const path=require('path') const server=http.createServer() server.on('request',(req,res)=>{ const url=req.url let filePath=path.join(__dirname,url) console.log(`正在请求地址:${url},实际对应地址为${filePath}`) }) server.listen(2022,()=>{ console.log('服务器正在运行,http://127.0.0.1:2022') })
这里的(req,res)=>{}也是回调函数。
详解
而 js 作为一门脚本语言却相对于java等传统面向对象语言有很大的不同之处, 除了 js 诡异的继承体系之外, 最令人着迷的一个特性就是回调函数, 当然也有很多人对他诟病, 笔者认为 回调函数 和 异步 是js语言特性的两大最为突出的点.
javascript 函数也是一种变量可以成为其他函数的参数, 我们喜欢在js中称之为回调函数, 另外js中的匿名函数可以作为函数参数使得回调函数的写法如鱼得水.
ps. 回调函数与 c 语言中的函数指针类似—指针指针指针!!!重要的事情说三遍
回调函数
function addSqua(num1, num2, callback){ var sum = num1 + num2; return callback(sum); } function squa(num){ return num*num; } let num = addSqua(1, 2, squa); console.log(num); //=>9
匿名回调函数
function addSqua(num1, num2, callback){ var sum = num1 + num2; return callback(sum); } let num = addSqua(1, 2, function squa(num){ return num*num; }); console.log(num); //=9
*上面的function squa(num){}函数,可以写成function (num){}匿名函数
模仿数组中的every方法
Array.prototype.myEvery = function (callback) { if (typeof callback === 'function') { for (let i = 0; i < this.length; i++) { if (callback(this[i])) { return false; } } return true; } return true; } let op = [3, 6, 'every', 9,'each']; op.myEvery(function (value) { console.log(value); }) // 3 // 6 // 'every' // 9 // 'each'
回调函数特点
不会立刻执行, 正如定义中给出的一样回调函数作为代码片段可以根据需要在其特定条件下执行, 回调函数作为参数传递给一个函数的时候,传递的只是函数的定义并不会立即执行。
this,ES6推出了箭头函数, 箭头函数的推出需要在写回调函数的时候格外注意, this 是指向所在函数的上下文对象, 如果在在ES6采用箭头函数则需要注意 this使用, 箭头函数中this并没有上下文关系直说, 有兴趣的可以查看ES6 阮一峰, 再次奉上传送门
回调函数的优点和使用场景是个闭包
回调函数是闭包的简单使用,也就是说它能访问到其外层定义的变量。
回调函数之美
-DRY,避免重复代码。
-可以将通用的逻辑抽象。
-业务逻辑分离 (it’s so beautiful - -)
-提高代码可维护性和可读性。
-加强代码可读性。
-分离专职的函数。
js回调函数的伟大之处是其他传统语言所没有的, 它可以实现业务逻辑分离, 相当于暴露给外界一个接口, 这一点像极了前后端分离架构中的 API 接口设计理念
这个世界没有 ‘银弹’ , 没有能够解决所有事情的一种方案, 由于js为异步而生, 回调函数用的最多的地方, 也是最适合的地方就是异步编程, 然而大量的使用会使得程序员的代码冗余, 有很大的不可读行, 体验极差, 索性让人高兴的事, 人们从来没有停止过对自己舒适度的追求。
链接:https://blog.csdn.net/qq459777807/article/details/118894627
链接:https://blog.csdn.net/dawn0718/article/details/122766775
标签:function,arr,函数,JavaScript,num,回调 From: https://www.cnblogs.com/vant-xie/p/16757078.html