第十一章 函数式编程

11.1 函数式编程与命令式编程

        以函数式范式进行开发并不简单;关键在于习惯这种范式的机制。我们编写一个例子来说明
差异。
        假设我们想打印一个数组中所有的元素。我们可以用命令式编程,声明的函数如下:

var printArray = function(array) {for (var i = 0; i < array.length; i++) {console.log(array[i]);}
};
printArray([1, 2, 3, 4, 5]);

        在上面的代码中,我们迭代数组,打印每一项。
        现在,我们试着把这个例子转换成函数式编程。在函数式编程中,函数就是摇滚明星。我们
关注的重点是需要描述什么,而不是如何描述。回到这一句:“我们迭代数组,打印每一项”。那
么,我们首先要关注的是迭代数据,然后进行操作,即打印数组项。下面的函数负责迭代数组:

var forEach = function(array, action) {for (var i = 0; i < array.length; i++) {action(array[i]);}
};

接下来,我们要创建另一个负责把数组元素打印到控制台的函数(考虑为回调函数),如下:

var logItem = function (item) {console.log(item);
};


最后,像下面这样使用声明的函数:
 

forEach([1, 2, 3, 4, 5], logItem);

        只需要上面这一行代码,我们就能描述我们要把数组的每一项打印到控制台。这是我们的第
一个函数式编程的例子!
有几点要注意:
 主要目标是描述数据,以及要对数据应用的转换;
 程序执行顺序的重要性很低,而在命令式编程中,步骤和顺序是非常重要的;
 函数和数据集合是函数式编程的核心;
 在函数式编程中,我们可以使用和滥用函数和递归,而在命令式编程中,则使用循环、赋值、条件和函数。

11.2 ES2015 和函数式编程

        有了ES2015的新功能,用JavaScript进行函数式编程变得更加容易了。我们来看一个例子。
        考虑我们要找出数组中最小的值。要用命令式编程完成这个任务,只要迭代数组,检查当前
的最小值是否大于数组元素;如果是,就更新最小值,代码如下:

var findMinArray = function(array) {var minValue = array[0];for (var i = 1; i < array.length; i++) {if (minValue > array[i]) {minValue = array[i];}}return minValue;
};
console.log(findMinArray([8, 6, 4, 5, 9])); //输出4


        用函数式编程完成相同的任务,可以使用Math.min函数,传入所有要比较的数组元素。我
们可以像下面的例子里这样,使用ES2015的解构操作符(...),把数组转换成单个的元素:

const min_ = function(array) {return Math.min(...array)
};
console.log(min_([8, 6, 4, 5, 9])); //输出4

 使用ES2015的箭头函数,我们可以进一步简化上面的代码:

const min = arr => Math.min(...arr);
console.log(min([8, 6, 4, 5, 9]));

11.3 JavaScript 函数式工具箱—— map、filter 和 reduce

        我们可以使用map函数,把一个数据集合转换或映射成另一个数据集合。先看一个命令式编
程的例子:

var daysOfWeek = [{name: 'Monday', value: 1},{name: 'Tuesday', value: 2},{name: 'Wednesday', value: 7}
];
var daysOfWeekValues_ = [];
for (var i = 0; i < daysOfWeek.length; i++) {daysOfWeekValues_.push(daysOfWeek[i].value);
}


        再以函数式编程来考虑同样的例子,代码如下:

var daysOfWeekValues = daysOfWeek.map(function(day) {return day.value;
});
console.log(daysOfWeekValues);


        我们可以使用filter函数过滤一个集合的值。来看一个例子:

var positiveNumbers_ = function(array) {var positive = [];for (var i = 0; i < array.length; i++) {if (array[i] >= 0) {positive.push(array[i]);}}return positive;
}
console.log(positiveNumbers_([-1, 1, 2, -2]));


        我们可以把同样的代码写成函数式的,如下:

var positiveNumbers = function(array) {return array.filter(function(num) {return num >= 0;})
};
console.log(positiveNumbers([-1, 1, 2, -2]));

        我们也可以使用reduce函数,把一个集合归约成一个特定的值。比如,对一个数组中的值
求和:

var sumValues = function(array) {var total = array[0];for (var i = 1; i < array.length; i++) {total += array[i];}return total;
};
console.log(sumValues([1, 2, 3, 4, 5]));


        上面的代码也可以写成这样:

var sum_ = function(array) {return array.reduce(function(a, b) {return a + b;})
};
console.log(sum_([1, 2, 3, 4, 5]));


        我们还可以把这些函数与ES2015的功能结合起来,比如解构操作符和箭头函数,代码如下:

const sum = arr => arr.reduce((a, b) => a + b);
console.log(sum([1, 2, 3, 4, 5]));


        我们再看另一个例子。考虑我们需要写一个函数,把几个数组连接起来。为此,可以创建另
一个数组,用于存放其他数组的元素。我们可以执行以下命令式的代码:

var mergeArrays_ = function(arrays) {var count = arrays.length,newArray = [],k =0;for (var i = 0; i < count; i++) {for (var j = 0; j < arrays[i].length; j++) {newArray[k++] = arrays[i][j];}}return newArray;
};
console.log(mergeArrays_([[1, 2, 3], [4, 5], [6]]));


        注意,在这个例子中,我们声明了变量,还使用了循环。现在,我们用JavaScript函数式编程
把上面的代码重写如下:

var mergeArraysConcat = function(arrays) {return arrays.reduce(function(p, n) {return p.concat(n);});
};
console.log(mergeArraysConcat([[1, 2, 3], [4, 5], [6]]));

        上面的代码完成了同样的任务,但它是面向函数的。我们也可以用ES2015使代码更加精简,
如下所示:
 

const mergeArrays = (...arrays) => [].concat(...arrays);
console.log(mergeArrays([1, 2, 3], [4, 5], [6]));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/230757.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ipa分发平台绑定域名有什么优势

大家好我是咕噜签名分发可爱多。今天跟大家分享一下&#xff0c;为什么建议大家将自己的域名绑定到分发平台&#xff08;比如咕噜分发&#xff09;。 将自己的域名绑定分发平台有几个原因和优势&#xff1a; 1. 专业性和品牌建设&#xff1a; 使用自己的域名可以让您的在线存…

【PTA-C语言】实验一-顺序结构

如果代码存在问题&#xff0c;麻烦大家指正 ~ ~有帮助麻烦点个赞 ~ ~ 实验一-顺序结构 7-1 逆序的三位数&#xff08;分数 10&#xff09;7-2 求整数均值&#xff08;分数 10&#xff09;7-3 日期格式化&#xff08;分数 10&#xff09;7-4 混合类型数据格式化输入&#xff08;…

消息队列有哪些应用场景?

分布式系统不同模块之间的通信&#xff0c;除了远程服务调用以外&#xff0c;消息中间件是另外一个重要的手段&#xff0c;在各种互联网系统设计中&#xff0c;消息队列有着广泛的应用。从本文开始&#xff0c;专栏进入分布式消息的模块&#xff0c;将讨论消息队列使用中的高频…

Windows如何安装使用TortoiseSVN客户端并实现公网访问本地SVN Server

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统&#xff0c;它与Apache Subversion&#xff08;SVN&#xff09;集成在一起&#xff0c;提供了一个用户友好的界面&#xff0c;方便用…

再谈低代码开发——值得所有程序设计和开发者重视的建议!

前几天看到关于“低代码开发”的话题&#xff0c;简单的谈了些自己的看法&#xff0c;也看了一些朋友们各抒己见的好文章&#xff0c;今天想结合我们实际使用的开发平台和大家再做些探讨。 在平台的简介中首先提出了这个大家一定很关心的问题&#xff1a; 一、“为什么使用低代…

三防平板电脑定制参数_三防移动平板终端方案

这是一款搭载了低功耗高性能CPU的三防平板电脑。采用联发科MT6771处理器&#xff0c;内置4GB64GB内存和八核处理器&#xff0c;提供出色的性能和运行速度。同时&#xff0c;它运行着最新的安卓Android 11.0系统&#xff0c;全屏支持和屏幕内容显示的优化使其更加方便和简单易用…

【华大】HC32F420JATB-LQ48学习资料及开发环境

1. 产品特点 ⚫ 84MHz Cortex-M4 32位CPU平台 ⚫ 128K 字节 FLASH 存储器&#xff0c;具有擦写保护功能 ⚫ 24K 字节 RAM 存储器 ⚫ 6 通道 DMAC ⚫多达 52 个通用 I/O 管脚 ⚫ 时钟、晶振 ‒ 外部高速晶振 8MHz~32MHz ‒ 内部高速时钟 22MHz~24MHz ‒ 内部低速时钟 3…

GoWin FPGA, GPIO--- startup1

一个Bank只能用一个电压&#xff0c;假如同一个Bank&#xff0c;在引脚里设置不同的电压&#xff0c;编译不过。 解释说明 2. 错误引脚限制 以上编译设置会导致编译错误。 Floor planner说明

猫粮哪个牌子好又安全?安全的主食冻干猫粮牌子推荐

由于猫咪是肉食动物&#xff0c;对蛋白质的需求很高&#xff0c;如果摄入的蛋白质不足&#xff0c;就会影响猫咪的成长。而冻干猫粮本身因为制作工艺的原因&#xff0c;能保留原有的营养成分和营养元素&#xff0c;所以冻干猫粮蛋白含量比较高&#xff0c;营养又高&#xff0c;…

智能仓储革命:科聪料箱机器人助力高效物流转型

料箱机器人即料箱AGV是一种智能化物流搬运设备&#xff0c;它可以代替人力完成出库入库和搬运工作&#xff0c;可根据出入库生产出货需求&#xff0c;将货物从起点运送到终点&#xff0c;自动柔性完成货到人货到点的操作。 提升仓储和物流效率的自动化利器 料箱机器人的投用能…

使用ArcMap10.8修改tif影像的地理坐标系

最近有个tif数据转坐标系给我整岔了&#xff0c;用了定义投影的方法&#xff0c;坐标系是有了&#xff0c;可是范围区域数值没有改变&#xff0c;导致转出来的数据没法用&#xff0c;后面成功了&#xff0c;记一下方法便于今后查找。 如下是我在arcmap中打开的tif影像坐标系&a…

各级行政区划shp文件,34个省份可下载,来源可靠

基本信息. 数据名称: 行政区划 数据格式: Shp文件 数据时间: 2021年 数据几何类型: 面 数据坐标系: WGS84坐标系 数据来源&#xff1a;网络公开数据、国务院发布的行政区划调整批复公告 数据可视化. 全国行政区划 广东省行政区划 深圳市行政区划 城市清单. 可下载数…

Swift爬虫采集唯品会商品详情

我有个朋友之前在唯品会开的店&#xff0c;现在想转战其他平台&#xff0c;想要店铺信息商品信息全部迁移过去&#xff0c;如果想要人工手动操作就有点麻烦了&#xff0c;然后有天找到我 &#xff0c;让我看看能不能通过技术手段实现商品信息迁移。嫌来无事&#xff0c;写了下面…

QT文件介绍

时间记录&#xff1a;2023/12/14 1.(.pro文件)项目管理文件 QT core guigreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c11DEFINES QT_DEPRECATED_WARNINGSSOURCES \main.cpp \mywidget.cppHEADERS \mywidget.h# Default rules for deployment. qnx: targe…

云原生之深入解析云原生架构的日志监控

一、什么是云原生架构的日志监控&#xff1f; 云原生架构的日志监控要求现代 Web 应用程序采用与传统应用程序略有不同的方法。部分原因是应用程序环境要复杂得多&#xff0c;包括从微服务中获取数据、使用 Kubernetes 和其他容器技术&#xff0c;以及在许多情况下集成开源组件…

Linux 进程信号

文章目录 信号的概览信号的产生信号的处理信号集操作信号的捕捉补充与说明 信号的概览 信号由软件或硬件产生发送给进程&#xff0c;进程对其做相应处理。信号是进程之间事件异步通知的一种方式&#xff0c;属于软中断。 Linux下的全部信号由指令kill -l查询 Linux 下指令的…

H264码流打包分析

H264码流打包分析 SODB 数据比特串&#xff0d;&#xff0d;&#xff1e;最原始的编码数据 RBSP 原始字节序列载荷&#xff0d;&#xff0d;&#xff1e;在SODB的后面填加了结尾比特&#xff08;RBSP trailing bits 一个bit“1”&#xff09;若干比特“0”,以便字节对齐。…

29道C++ 面向对象高频题整理(附答案背诵版)

1、什么是类&#xff1f; 在C中&#xff0c;类是一种用户定义的数据类型&#xff0c;它可以包含数据成员和函数成员。数据成员用于存储与类相关的状态&#xff0c;而函数成员可以定义对这些数据进行操作的方法。可以把类想象为一个蓝图&#xff0c;根据这个蓝图可以创建对象&a…

k8s中ConfigMap、Secret创建使用演示、配置文件存储介绍

目录 一.ConfigMap&#xff08;cm&#xff09; 1.适用场景 2.创建并验证configmap &#xff08;1&#xff09;以yaml配置文件创建configmap&#xff0c;验证变化是是否同步 &#xff08;2&#xff09;--from-file以目录或文件 3.如何使用configmap &#xff08;1&#x…

Ubuntu 虚拟机环境,编译AOSP源码

环境 : VMware虚拟机 Ubuntu 20.04.3 LTS 搭建配置开发环境 sudo apt-get install git-core gnupg flex bison build-essential zip curl zlib1g-dev gcc-multilib g-multilib libc6-dev-i386 libncurses5 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z1-dev libgl…