一、为什么函数是一等公民
1.1. 什么是一等公民
在编程语言中,当说到“一等公民”(First-class Citizen)这个术语时,它指的是语言中的基本抽象单位,它们被赋予了与其他基本数据类型(如数字、字符串、布尔值等)相同的地位和能力
1.2. 为什么称呼为“一等公民”
- 在1967年的论文《Fundamental Concepts in Programming Languages》中,斯特雷奇提出了
一等公民的概念,用以描述在编程语言中具有特定地位的实体 - 其实一等这个词汇,就有一种优越性的表达含义,但在这里,其实是表示地位及重要性。简单的理解的话,就是编程语言之中一旦有内容被称为
一等公民,该内容就是这门语言的核心内容
1.2.1. 实体定义
- 我们对
一等公民的定义是:具备特定地位的实体。但这定义要怎么理解呢?毕竟就目前来看还是有点抽象 -
- 可以被存储在数据结构中(如数组、列表、哈希表等)
- 可以参数传递
- 可以有返回值
- 可以被赋值给其他标识符
- 具备这些特性的内容,就被称为一等公民。在JavaScript中,是函数,而在Java中,则是对象
-
- 不同语言的一等公民所指的其实都不尽相同
- 但具备的特点是一样的
二、高阶函数
2.1. 什么是高阶函数
在JavaScript中,高阶函数是指至少满足以下一个条件的函数:
- 接收一个或多个函数作为参数
- 返回一个函数
2.2. 挑选偶数
- 从高阶函数的定义来看,我们的封装函数小案例,满足第一点条件,也是属于一种高阶函数
-
- 我们通过正常使用和高阶函数使用,来分别实现原生JS的挑选偶数案例
2.2.1. 普通方式实现
- 我们一般的实现思路是在拥有JS基础知识情况下,正常的实现方式:
-
- 创建空数组用来接收偶数
- 遍历需要筛选偶数的数组
- 对每个数字进行判断是否为偶数
- 为偶数则填入创建的空数组
- 正常进行实现,其实是需要四个步骤的,所有的步骤都由我们手动的进行实现
//普通使用
var nums = [2,4,5,8,12,45,23]
var newNums = []
for(var i = 0;i<nums.length;i++){
var num = nums[i]
if(num % 2 === 0){
newNums.push(num)
}
}
console.log(newNums)
//[ 2, 4, 8, 12 ]
2.2.2. filter过滤器实现
- filter过滤器是数组之中的方法
-
-
element: 当前正在处理的数组元素
-
index(可选): 当前元素的索引
-
array(可选): 调用
filter的数组 -
语法:array.filter(callback(element[, index[, array]])[, thisArg])
-
callback: 函数,测试数组的每个元素。返回
true表示保留元素,返回false表示丢弃元素thisArg(可选): 执行
callback时使用的this值(暂时跳过,我们后面章节会讲this)
-
- 我们传入的其实是一个函数,而这个函数在内部会被调用。此时就会被称为回调函数callback,回调就是回头会调用的意思
-
- 所以实际上我们filter的参数只有两个,一个是回调函数,一个是绑定this。后者我们暂时不考虑
- 前者回调函数可接收三个参数
- 该高阶函数是过滤的意思,这说明了,我们可以直接对遍历的参数本身进行判断,产生的判断结果为布尔值,则会决定了当前数据是否返回,而不是返回布尔值本身。这就是该高阶函数
过滤本身所具备的含义
//filter,对数组进行过滤,是数组中的一个方法,传入三个参数(第一个是数组中遍历的值,第二个是数组的对应下标,第三个是我们当前数组的引用=>就是整个数组传进来),返回值是另外一个新的数组
var nums = [2,4,5,8,12,45,23]
//方式1:明显的函数特征
var evenNumbers = numbers.filter(function(number) {
return number % 2 === 0; // 返回条件:元素是偶数
});
//方式2:箭头函数省略掉function
var newNums = nums.filter((item,index,array)=>{
return item % 2 === 0
})
console.log(newNums);
//[ 2, 4, 8, 12 ]
-
所以在了解我们的需求之后,只需要用到回调函数的第一个参数的情况下,我们连小括号都能省略掉
-
这个回调函数,我们nums数组内的每一个数字都会调用一次
-
同时可以注意到,我们没有了括号之后,不需要return。这是因为
{}其实是函数的作用域,而一旦出现了作用域就会隔绝变量的提升,此时想要传递出去就需要return -
不使用
{}的条件是,我们的逻辑非常简短,简短到就只有一行内容就可以使用 -
并且由于filter是使用在数组的方法,回调函数至少对一个元素返回
true,否则返回一个空数组
var nums = [1, 2, 3, 4, 5, 6];
//方式3:省略掉小括号
var newNums = nums.filter(n => n % 2 === 0);
console.log(newNums); // 输出: [2, 4, 6]`