在JavaScript
中,函数是一等公民,它们是一种特殊类型的对象,也就是Function对象
。更确切地说,函数是用Function()构造函数
创建的Function对象
,既然函数就是对象,那么函数就可以作为另外一些函数的实参进行传递。
1. 回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。(以上节选自百度百科)
通俗来讲,一个函数A作为参数传递给另一个函数B,函数A在函数B中被调用,我们就称函数A为回调函数。再简单点讲就是:作为参数传递的函数 就是回调函数。
function aa(x){
console.log(x);
}
function bb(y){
// 在bb函数内调用传过来的函数
// 我们称作为参数传过来的函数为回调函数
y('我好帅啊!');
y.call(null, '看我帅不帅');
}
// 将aa函数作为形参传递给bb函数
// 切记不要在aa后面加()
bb(aa());
我们可以看到,我们定义的aa函数,其实aa只是存放的只是其函数对象在堆内存中的地址,基本上就像下图表示的一样:
我们在将aa
作为实参传递给bb函数
的时候,其实传递的是aa
中保存的函数对象的内存地址,并不是真正调用了其指向的函数。因此,我们的函数aa
传递的过程中并没有被执行,只有当我们在函数bb
中对其进行调用的时候才真正执行,也就是在某个特定时间点被“回调”。
使用匿名函数作为回调函数
function bb(y){
y('我好帅啊!');
y.call(null, '看我帅不帅');
}
// 使用匿名函数
bb(function(x){
console.log(x)
});
回调函数其实是闭包函数
回调函数在包含它的函数内的某一点执行,就好像这个回调函数是在包含它的函数中定义的一样。且回调函数可以访问其它作用域内变量,因此,回调函数可以算是闭包函数。
function aa(x){
console.log(x);
}
function bb(callback){
var word = '看我帅否'
callback(word);
}
bb(aa);
2. 高阶函数(方法)
高阶函数是对其他函数进行操作的函数,可以将它们作为参数或返回它们。 简单来说,高阶函数是一个函数,它接收函数作为参数或将函数作为输出返回
按照高阶函数的定义,我们前面定义的bb
函数就是个高阶函数。
2.1 数组内置高阶函数(方法)
2.1 map方法
map方法通过将输入数组中的每个元素作为参数来调用提供的回调函数来创建一个新数组。 它会从回调函数中获取每个返回的值,并使用这些值创建一个新数组。
通俗来说就是:会将数组中的每一个值带入到回调函数中执行,把执行后的结果收集起来,放到一个新创建的数组中。
// 基本语法
array.map(function(currentValue,index,arr), thisValue)
回调函数参数说明:
代码演示:
// 执行过程展示
function ca(value, index, arr){
console.log(value,index,arr, '=====');
}
var a = [555, 666, 888, 999];
a.map(ca);
// 使用展示
function ca(value,index,arr){
return value + 1;
}
var a = [555, 666, 888, 999];
var b = a.map(ca);
console.log(b);
2.2 reduce 方法
reduce方法
接收一个回调函数作为累加器,然后将数组中的每一个元素依次传入回调函数中并执行(第一次传入数组中的2个值)。
回调函数参数说明:
代码演示:
// 执行过程查看
/**
* 定义回调函数的时候,前两个参数为必须要提供的
* total 为初始值,或者上一次调用回调返回的值
*/
function ca(total, currentValue, currentIndex, arr){
console.log(total, currentValue);
}
var a = [555, 666, 888, 999];
var b = a.reduce(ca);
// 实际使用1 求和
function ca(total, currentValue, currentIndex, arr){
return total + currentValue;
}
var a = [100, 200, 300, 400];
var b = a.reduce(ca);
console.log(b);
// 我们看一下上面的执行过程:
// 第一次将 100 和 200 传入到回调函数中前两个参数,通过运算,返回值为300
// 第二次将返回值300 和 300 传入回调函数中前两个参数,通过运算,返回值为600
// 第三次将返回值600 和 400 传入回调函数中前两个参数,通过运算,返回值为1000
// 最终返回值为 1000
// 实际使用2 求最大值
function ca(total, currentValue, currentIndex, arr){
if(total > currentValue){
return total;
}else{
return currentValue;
}
}
var a = [500, 600, 300, 800, 200];
var b = a.reduce(ca);
console.log(b);
// 我们看一下上面的执行过程:
// 第一次将 500 和 600 传入到回调函数中前两个参数,通过运算,返回值为600
// 第二次将返回值600 和 300 传入回调函数中前两个参数,通过运算,返回值为600
// 第三次将返回值600 和 800 传入回调函数中前两个参数,通过运算,返回值为800
// 第四次将返回值800 和 200 传入回调函数中前两个参数,通过运算,返回值为800
// 最终返回值为 800
2.3 filter 方法
用于筛选数组中满足条件的元素,返回一个筛选后的新数组。
回调函数参数说明:
代码演示:
// 执行过程演示
var a = [500, 600, 300, 800, 200];
function ca(item){
console.log(item);
}
a.filter(ca);
// 实用演示
// 求出小于500的值
var a = [500, 600, 300, 800, 200];
function ca(item){
if (item < 500){
return true;
}
}
var b = a.filter(ca);
console.log(b);
// 上面的执行过程是这样的:
// 将数组中的每一个元素依次传入到回调函数中,
// 如果回调函数中运算结果返回为真,则将该元素选中
// 将选中的元素放到一个新数组中最后返回
2.4 every 方法
用于判断数组中的每一项元素是否都满足条件,返回一个布尔值,类似and操作。
代码演示:
var a = [500, 600, 300, 800, 200];
function ca(x){
console.log(arguments);
if(x < 1000){
return true;
}
}
// 将数组中的值依次传入回调函数中,如果每次返回的都是真,那么整体为真
var b = a.every(ca);
console.log(b);
2.5 some 方法
用于判断数组中的是否存在满足条件的元素,返回一个布尔值,类似or操作。
代码演示:
var a = [500, 600, 300, 800, 200];
function ca(x){
console.log(arguments);
if(x < 400){
return true;
}
}
// 将数组中的值依次传入回调函数中,如果有一次返回值为真,那么整体为真
var b = a.some(ca);
console.log(b);