函数式编程 -- 函数是一等公民、高阶函数、闭包

214 阅读3分钟

前言

学习函数式编程,首先要了解函数式编程相关的概念。

一、函数是一等公民

1. 一等公民的定义

根据维基百科,编程语言中一等公民的概念是由英国计算机学家Christopher Strachey提出来的,时间则早在上个世纪60年代。但是他并没有严格的给出一等公民的定义。 关于一等公民的定义,在《Programming Language Pragmatics》书中给出了答案。

In general, a value in a programming language is said to have first-class status if it can be passed as a parameter, returned from a subroutine, or assigned into a variable.

在编程语言中,一等公民可以作为函数参数,可以作为函数返回值,也可以赋值给变量。

2. 为什么说函数是一等公民

在JavaScript中,函数可以使用函数表达式的方式进行定义,因此,函数可以存储在变量中;因为ECMAScript中函数名本身就是变量,所以函数也可以作为值来使用。也就是说,不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另一个函数的结果返回(闭包)。

  • 把函数赋值给变量

    代码如下(示例):

    // 定义匿名函数,然后把函数赋值给变量
    let fn = function () {
    	console.log("Hello First-class Function")
    }
    fn()
    
    // 把函数保存到其他数据结构,如Object中
    const student = {
    	name: "Alison",
    	age: 27,
    	study: function () {
    		return "Study"
    	}
    }
    

二、高阶函数(Higher-order function)

1. 什么是高阶函数

  • 高阶函数 * 可以把函数作为参数传递给另一个函数 * 可以把函数作为另一个函数的返回结果

  • 函数作为参数

    代码如下(示例):

    // forEach 
    function forEach (array, fn) { 
        for (let i = 0; i < array.length; i++) { 
            fn(array[i]) 
        } 
    }
    
    // filter 
    function filter (array, fn) { 
        let results = [] 
        for (let i = 0; i < array.length; i++) { 
            if (fn(array[i])) { 
                results.push(array[i]) 
            } 
        }
        return results 
    } 
    
  • 函数作为返回值

    代码如下(示例):

    function makeFn () { 
        let msg = 'Hello function' 
        return function () { 
            console.log(msg) 
        } 
    }
    // makeFn()(),与下面的调用方式等价
    const fn = makeFn() 
    fn() 
    

2. 使用高阶函数的意义

  • 抽象可以帮我们屏蔽细节,只需要关注与我们的目标
  • 高阶函数是用来抽象通用的问题

3. 常用高阶函数

  • forEach
  • map
  • filter
  • every
  • some
  • find/findIndex
  • reduce
  • sort
  • ……

详情参见:数组(Array)的常用方法

三、闭包(closure)

1. 闭包的目的

  • 为了设计私有的方法和变量。

2. 什么是闭包,为什么要用它?

  • 闭包是指有权访问另一个函数作用域中变量的函数。

3. 创建闭包的最常见的方式

  • 就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量。

    代码如下(示例):

    // 根据对象中的某个属性,进行排序
    function createComparisonFunction(propertyName) {
    	return function(object1, object2) {
    		var value1 = object1[propertyName];
    		var value2 = object2[propertyName];
    		if (value1  > value1 ) {
    			return 1
    		} else if (value1  < value1) {
    			return -1
    		} else {
    			return 0
    		}		
    	}
    }
    

4. 闭包的特性

  1. 函数内再嵌套函数;
  2. 内部函数可以引用外层的参数和变量;
  3. 参数和变量不会被垃圾回收机制回收。

5. 闭包的优缺点

  • 优点
  1. 可以避免全局变量的污染。
  2. 利用闭包可以突破作用链域。
  • 缺点 闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。

总结

函数是一等公民是高阶函数、柯里化等的基础。熟知高阶函数、闭包等,有利于我们学好函数式编程。

参考 www.cnblogs.com/fundebug/p/…