JS高级-函数一等公民

160 阅读4分钟

一、为什么函数是一等公民

1.1. 什么是一等公民

在编程语言中,当说到“一等公民”(First-class Citizen)这个术语时,它指的是语言中的基本抽象单位,它们被赋予了与其他基本数据类型(如数字、字符串、布尔值等)相同的地位和能力

1.2. 为什么称呼为“一等公民”

  • 在1967年的论文《Fundamental Concepts in Programming Languages》中,斯特雷奇提出了一等公民的概念,用以描述在编程语言中具有特定地位的实体
  • 其实一等这个词汇,就有一种优越性的表达含义,但在这里,其实是表示地位及重要性。简单的理解的话,就是编程语言之中一旦有内容被称为一等公民,该内容就是这门语言的核心内容

1.2.1. 实体定义

  • 我们对一等公民的定义是:具备特定地位的实体。但这定义要怎么理解呢?毕竟就目前来看还是有点抽象
    1. 可以被存储在数据结构中(如数组、列表、哈希表等)
    2. 可以参数传递
    3. 可以有返回值
    4. 可以被赋值给其他标识符
  • 具备这些特性的内容,就被称为一等公民。在JavaScript中,是函数,而在Java中,则是对象
    • 不同语言的一等公民所指的其实都不尽相同
    • 但具备的特点是一样的

二、高阶函数

2.1. 什么是高阶函数

在JavaScript中,高阶函数是指至少满足以下一个条件的函数:

  1. 接收一个或多个函数作为参数
  2. 返回一个函数

2.2. 挑选偶数

  • 从高阶函数的定义来看,我们的封装函数小案例,满足第一点条件,也是属于一种高阶函数
    • 我们通过正常使用和高阶函数使用,来分别实现原生JS的挑选偶数案例

2.2.1. 普通方式实现

  • 我们一般的实现思路是在拥有JS基础知识情况下,正常的实现方式:
    1. 创建空数组用来接收偶数
    2. 遍历需要筛选偶数的数组
    3. 对每个数字进行判断是否为偶数
    4. 为偶数则填入创建的空数组
  • 正常进行实现,其实是需要四个步骤的,所有的步骤都由我们手动的进行实现
//普通使用  
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 = [123456];
//方式3:省略掉小括号
var newNums = nums.filter(n => n % 2 === 0);
console.log(newNums); // 输出: [2, 4, 6]`