JS 函数式编程思维简述(二):高阶函数

栏目: JavaScript · 发布时间: 6年前

内容简介:高阶函数(High-Order Function)是函数式编程思维中的重要条件,而满足该条件的编程语言则需要将函数作为该语言的将函数视作一等公民的语言有:JavaScript、Golang、Python、Scala、Lua、Lisp、Scheme等。同时,有着越来越多的其他语言看上了函数式编程的出彩之处,以其特有的方式实现着符合自身编程方式的在
  1. 简述
  2. 无副作用(No Side Effects)
  3. 高阶函数(High-Order Function)
  4. 科里化(Currying)
  5. 闭包(Closure)
  6. 不可变(Immutable)
  7. 惰性计算(Lazy Evaluation)
  8. Monad

一等公民

高阶函数(High-Order Function)是函数式编程思维中的重要条件,而满足该条件的编程语言则需要将函数作为该语言的 一等公民 来看待。符合 一等公民 的条件是:

  • 函数可以作为一种数据类型的值,赋值于一个变量;
  • 函数可以作为参数,在其他函数中进行传递;
  • 函数可以作为返回值,在其他函数中返回;
JS 函数式编程思维简述(二):高阶函数

image

将函数视作一等公民的语言有:JavaScript、Golang、 Python 、Scala、 Lua 、Lisp、Scheme等。同时,有着越来越多的其他语言看上了函数式编程的出彩之处,以其特有的方式实现着符合自身编程方式的 高阶函数

函数类型

JavaScript 中,函数是数据类型 object 的子类型——即是指一种对象类型。我们可以通过 typeof 操作符检测一个值是否是一个函数类型:

// 一个函数声明
function foo(x){
    return x + 10;
}
typeof foo; // 返回值:'function'

然而,实际上在 JavaScript 中,函数并非是 基本的数据类型 ,函数隶属于对象类型。能够使用 typeof 操作符进行检测仅仅是语言提供的便利:

// 声明一个 number 类型的变量
const n = 13;
// 一个函数声明
function foo(x){
    return x + 10;
}
typeof foo; // 结果:'function'
typeof n; // 结果:'number'

// 检测 n 所持有的值是否是对象
n instanceof Object; // 结果:false

// 检测 foo 所持有的值是否是对象
foo instanceof Function; // 结果:true
Function instanceof Object; // 结果:true
foo instanceof Object; // 结果:true

可见,函数是一个隶属于 Function 的对象,而 Function 本身又隶属于顶层 Object ,是它的子对象。因此,一个函数的实例,也隶属于 Object ,他们之间拥有间接的继承关系。

很多有 面向对象 经验的同学可能会想,实例化对象不是通过 new 关键字调用类的构造函数来进行的吗?这个问题很简单:拿 Java 例举, Java 中拥有字面量形式的对象声明方式 String str = "I like Java!"; ,声明变量 str 的过程中实际上也构建了一个字符串对象,并没有显式的使用关键字 new

JavaScript 中,以字面量的方式构建对象有很多种,比如:

// 数组字面量
const arr = [1, 2, 3];
// 对象字面量
const obj = {id : 'xx001'};
// 函数字面量
function foo(){}            // 函数声明
const bar = function(){}    // 函数表达式
const baz = (x) => x + 3;   // ES6提供的lambda表达式函数

函数入参

由于函数也是一个对象,因此函数也可以作为其他函数的参数,作为入参:

// 一个函数声明
const add2 = (x) => x + 2;          // 参数x基础上加2的函数
const sub2 = (x) => x - 2;          // 参数x基础上减2的函数
const result = (y, f) => y * f(y);  // 参数y基础上乘以 函数参数f 的运算结果

result(4, add2);    // 结果: 24
result(4, sub2);    // 结果: 8

JavaScript 内置对象中,也有非常多的函数入参实例,比如 Array.prototype.map 函数的简单实现:

// 一个高仿的 Array.prototype.map 函数
const map = function(arr, f){
    const t = []; 
    for(let i=0;i<arr.length; t.push(f(arr[i],i++,arr)));
    return t;
}
// 声明一个数组
const a1 = [1,2,3,4];
// map函数调用:参数 f 所示为每一个值乘以3,并且返回一个新数组
const a2 = map(a1, (e) => e*3); // 结果:[3, 6, 9, 12]

函数返回值

函数可以作为参数,当然也可以作为返回值。作为返回值的函数,常用于缓存上一个函数的执行状态:

// 一个函数声明
const add2 = (x) => x + 2;          // 参数x基础上加 2 的函数
const mul2 = (x) => x * 2;          // 参数x基础上乘以 2 的函数

// 该函数用于计算,计算结果不会直接得出,而是缓存了用于计算的两个函数
const calc = function(f1, f2){
    return (y) => f1( f2(y) );
}

// 根据缓存顺序不同,生成的新的函数执行过程也不同
const c01 = calc(add2, mul2); 
c01(3); // 结果: 8

const c02 = calc(mul2, add2); 
c02(3); // 结果:10

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

马化腾自述-我的互联网思维

马化腾自述-我的互联网思维

赵黎 / 石油工业出版社 / 2014-8-1 / 35

马化腾自述:我的互联网思维》讲述了些人说移动互联网就是加了“移动”两个字,互联网十几年了,移动互联网应该是个延伸。我的感受是,移动互联网远远不只是一个延伸,甚至是一个颠覆。互联网是一个开放交融、瞬息万变的大生态,企业作为互联网生态里面的物种,需要像自然界的生物一样,各个方面都具有与生态系统汇接、和谐、共生的特性。开放和分享并不是一个宣传口号,也不是一个简单的概念。开放很多时候被看作一种姿态,但是我......一起来看看 《马化腾自述-我的互联网思维》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换