javascript基础二十五:说说你对函数式编程的理解?优缺点?

news2024/12/23 19:43:07

在这里插入图片描述
一、是什么

函数式编程是一种"编程范式"(programming paradigm),一种编写程序的方法论

主要的编程范式有三种:命令式编程,声明式编程和函数式编程

相比命令式编程,函数式编程更加强调程序执行的结果而非执行的过程,倡导利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,而非设计一个复杂的执行过程

举个粟子,将数组每个元素进行平方操作,命令式编程与函数式编程如下

// 命令式编程
var array = [0, 1, 2, 3]
for(let i = 0; i < array.length; i++) {
    array[i] = Math.pow(array[i], 2)
}

// 函数式方式
[0, 1, 2, 3].map(num => Math.pow(num, 2))

简单来讲,就是要把过程逻辑写成函数,定义好输入参数,只关心它的输出结果

即是一种描述集合和集合之间的转换关系,输入通过函数都会返回有且只有一个输出值

在这里插入图片描述
可以看到,函数实际上是一个关系,或者说是一种映射,而这种映射关系是可以组合的,一旦我们知道一个函数的输出类型可以匹配另一个函数的输入,那他们就可以进行组合

二、概念

纯函数

函数式编程旨在尽可能的提高代码的无状态性和不变性。要做到这一点,就要学会使用无副作用的函数,也就是纯函数

纯函数是对给定的输入返还相同输出的函数,并且要求你所有的数据都是不可变的,即纯函数=无状态+数据不可变

在这里插入图片描述
举个粟子:

let double = value=>value*2;

特性:

  • 函数内部传入指定的值,就会返回确定唯一的值
  • 不会造成超出作用域的变化,例如修改全局变量或引用传递的参数

优势:
使用纯函数,我们可以产生可测试的代码

test('double(2) 等于 4', () => {
  expect(double(2)).toBe(4);
})

不依赖外部环境计算,不会产生副作用,提高函数的复用性
可读性更强 ,函数不管是否是纯函数 都会有一个语义化的名称,更便于阅读
可以组装成复杂任务的可能性。符合模块化概念及单一职责原则

高阶函数

在我们的编程世界中,我们需要处理的其实也只有“数据”和“关系”,而关系就是函数

编程工作也就是在找一种映射关系,一旦关系找到了,问题就解决了,剩下的事情,就是让数据流过这种关系,然后转换成另一个数据,如下图所示

在这里插入图片描述

在这里,就是高阶函数的作用。高级函数,就是以函数作为输入或者输出的函数被称为高阶函数

通过高阶函数抽象过程,注重结果,如下面例子

const forEach = function(arr,fn){
    for(let i=0;i<arr.length;i++){
        fn(arr[i]);
    }
}
let arr = [1,2,3];
forEach(arr,(item)=>{
    console.log(item);
})

上面通过高阶函数 forEach来抽象循环如何做的逻辑,直接关注做了什么

高阶函数存在缓存的特性,主要是利用闭包作用

const once = (fn)=>{
    let done = false;
    return function(){
        if(!done){
            fn.apply(this,fn);
        }else{
            console.log("该函数已经执行");
        }
        done = true;
    }
}

柯里化

柯里化是把一个多参数函数转化成一个嵌套的一元函数的过程

一个二元函数如下:

let fn = (x,y)=>x+y;

转化成柯里化函数如下:

const curry = function(fn){
    return function(x){
        return function(y){
            return fn(x,y);
        }
    }
}
let myfn = curry(fn);
console.log( myfn(1)(2) );

上面的curry函数只能处理二元情况,下面再来实现一个实现多参数的情况

// 多参数柯里化;
const curry = function(fn){
    return function curriedFn(...args){
        if(args.length<fn.length){
            return function(){
                return curriedFn(...args.concat([...arguments]));
            }
        }
        return fn(...args);
    }
}
const fn = (x,y,z,a)=>x+y+z+a;
const myfn = curry(fn);
console.log(myfn(1)(2)(3)(1));

关于柯里化函数的意义如下:

  • 让纯函数更纯,每次接受一个参数,松散解耦
  • 惰性执行

组合与管道

组合函数,目的是将多个函数组合成一个函数

举个简单的例子:

function afn(a){
    return a*2;
}
function bfn(b){
    return b*3;
}
const compose = (a,b)=>c=>a(b(c));
let myfn =  compose(afn,bfn);
console.log( myfn(2));

可以看到compose实现一个简单的功能:形成了一个新的函数,而这个函数就是一条从 bfn -> afn 的流水线

下面再来看看如何实现一个多函数组合:

const compose = (…fns)=>val=>fns.reverse().reduce((acc,fn)=>fn(acc),val);

compose执行是从右到左的。而管道函数,执行顺序是从左到右执行的

const pipe = (…fns)=>val=>fns.reduce((acc,fn)=>fn(acc),val);

组合函数与管道函数的意义在于:可以把很多小函数组合起来完成更复杂的逻辑

三、优缺点

优点

  • 更好的管理状态:因为它的宗旨是无状态,或者说更少的状态,能最大化的减少这些未知、优化代码、减少出错情况
  • 更简单的复用:固定输入->固定输出,没有其他外部变量影响,并且无副作用。这样代码复用时,完全不需要考虑它的内部实现和外部影响
  • 更优雅的组合:往大的说,网页是由各个组件组成的。往小的说,一个函数也可能是由多个小函数组成的。更强的复用性,带来更强大的组合性
  • 隐性好处。减少代码量,提高维护性

缺点:

  • 性能:函数式编程相对于指令式编程,性能绝对是一个短板,因为它往往会对一个方法进行过度包装,从而产生上下文切换的性能开销
  • 资源占用:在 JS 中为了实现对象状态的不可变,往往会创建新的对象,因此,它对垃圾回收所产生的压力远远超过其他编程方式
  • 递归陷阱:在函数式编程中,为了实现迭代,通常会采用递归操作

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

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

相关文章

C SS复习笔记

1.img标签 img的src属性是图片显示不出来时显示的文字 ing的title属性是光标放到图片上&#xff0c;提示的文字 2.a标签 a标签的target属性表示打开窗口的方式&#xff0c;默认的值是_self表示当前窗口的打开页面&#xff0c;_blank表示新窗口打开页面。 a标签的href链接分…

2023.06.04 学习周报

文章目录 摘要文献阅读1.题目2.背景3.方案4.本文贡献5.模型5.1 图注意力形式5.2 superGAT 6.实验7.结论 有限元数学建模深度学习1.高斯扩散2.原理 总结 摘要 This week, I read a computer science about GNN. At present, the attention mechanism of graph neural network i…

Go Web下GORM框架使用(二)

〇、前言 本文将会写一个前后端分离的的小项目&#xff0c;本文将会只实现后端。 一、定义全局变量与模型 本文需要一个数据库&#xff0c;因此将这个数据库定义为全局变量将会非常轻松。 var (DB *gorm.DB )type Todo struct {ID int json:"id"Title s…

【C#图解教程】第六章 方法(下)

输出参数 函数的输出只有返回值有时不太够&#xff0c;此时需要用到输出参数&#xff0c;用修饰词out声明 输出参数的要求与引用参数类似&#xff0c;需要是变量&#xff0c;此外&#xff0c;输出参数也是实参的别名&#xff0c;指向堆中同一对象。 输出参数与引用参数的不同在…

【实用篇】Elasticsearch03

文章目录 分布式搜索引擎031.数据聚合1.1.聚合的种类1.2.DSL实现聚合1.2.1.Bucket聚合语法1.2.2.聚合结果排序1.2.3.限定聚合范围1.2.4.Metric聚合语法1.2.5.小结 1.3.RestAPI实现聚合1.3.1.API语法1.3.2.业务需求1.3.3.业务实现 2.自动补全2.1.拼音分词器2.2.自定义分词器2.3.…

【人工智能】— Support Vector Machines 支持向量机

【人工智能】— Support Vector Machines 支持向量机 支持向量机概述支持向量机支持向量机原理介绍分类间距&#xff08;Classification Margin&#xff09; 支持向量机概述 找到使间隔最大化的超平面>B1比B2更好 支持向量机 研究起因&#xff1a;如何找到最优的切分面 分…

制作酷炫可视化大屏利器--分享10种比较流行的开源免费的图表库

在开发可视化项目的过程中往往涉及到可视化图表, 多酷炫的报表, 大屏, 都用了非常多的图表, 接下来我和大家分享一些比较流行的开源免费的图表库. 分享10种比较流行的开源免费的图表库 1&#xff0c;Frappe Charts2&#xff0c;Recharts3&#xff0c;Protovis4&#xff0c;dygr…

Docker快速入门(分分钟钟就能上手)

Docker的思想 集装箱&#xff1a;会将所有需要的内容放到不同的集装箱中&#xff0c;谁需要这些环境就直接拿到这个集装箱就可以了。标准化&#xff1a; 运输的标准化&#xff1a;Docker有一个码头&#xff0c;所有上传的集装箱都放在了这个码头上&#xff0c;当谁需要某一个环…

设计模式-01.设计思想

设计思想 此系列文章非本人原创&#xff0c;是学习笔记。 下面讲一些常见的设计思想 基于接口而非实现编程 这个原则非常重要&#xff0c;是一种非常有效的提高代码质量的手段&#xff0c;在平时的开发中特别经常被用到。 如何解读原则中的“接口”二字&#xff1f; “基于…

python面向对象操作1(速通版)

目录 一、高阶函数 1.lambda函数 2.lambda函数注意事项 3.map用法 4.map和lambda函数配合 二、reduce函数 1.reduce基本应用 2.reduce和匿名函数配合 三、filter()函数 1.简单用法 2.高阶应用 四、列表排列方法&#xff08;key和lambda问题&#xff09; 1.正常排序…

Node服务器和常见模块

1 Node服务器开发 2 fs模块-文件系统 3 event模块-事件处理 4 认识二进制和buffer 5 Buffer的创建方式 6 Buffer的源码解析 node 的fs模块操作&#xff1a; 这里主要讲node如何进行读取文件&#xff0c;操作文件。服务器该有的操作node都有。 node的fs读取文本文件内容的d…

自定义starter

第一步、创建 xxx-spring-boot-starter 的spring Initializr模块 第二步、删除不需要的内容&#xff08;启动类、除下面spring-boot-starter的其它依赖&#xff0c;maven编译插件&#xff09; <dependency><groupId>org.springframework.boot</groupId><…

linux理解软硬链接

软硬连接 在linux下面链接文件有两种&#xff0c;一种是类似window的快捷方式功能的文件&#xff0c;可以让你快速链接到目标文件&#xff08;或目录&#xff09;&#xff0c;叫做软链接&#xff0c;另一种则是通过文件系统的inode链接来产生新的文件名&#xff0c;而不是产生…

Linux 常用开发工具(yum、vim)

绪论 耐心是一切聪明才智的基础。—— 柏拉图。本章进入到Linux下的一些常用的工具&#xff0c;这些工具能帮助我们去更好的使用Linux操作系统。 话不多说安全带系好&#xff0c;发车啦&#xff08;建议电脑观看&#xff09;。 附&#xff1a;红色&#xff0c;部分为重点部分&a…

[MAUI程序设计] 用Handler实现自定义跨平台控件

文章目录 Handler与Xamarin.Forms实现的区别为什么要用Handler代替Renderer解耦生命周期管理更细粒度的控制 用Effect来实现呢&#xff1f;自定义手势监听控件在各平台上实现TouchRecognizeriOS中的实现Android中的实现Windows中的实现 创建控件使用控件最终效果项目地址 今天来…

使用 Kubeadm 和 CRI-O 在 Rocky Linux 8 上安装 Kubernetes 集群

在 Rocky Linux 8 上安装 Kubernetes 集群。毫无疑问&#xff0c;Kubernetes 将继续改变我们大规模部署和管理业务应用程序的方式。无论用于部署应用程序的模型是手动还是通过 CI/CD 管道&#xff0c;Kubernetes 仍然是处理编排、管理和扩展应用程序的最佳选择。 对于那些不知…

一劳永逸的方法解决函数scanf报错问题

目录 scanf报错示例 代码 报错提醒 报错翻译 解决方案1&#xff08;不建议&#xff09;:将scanf换成scanf_s&#xff1b; 解决方案2&#xff08;临时解决&#xff09;&#xff1a; 解决方案3&#xff08;建议&#xff09;&#xff1a; 方法1&#xff08;建议&#xff09…

javaScript蓝桥杯----资讯接口

目录 一、介绍二、准备三、目标四、代码五、知识点1.res.end()2.res.end与res.send 六、完成 一、介绍 随着技术的发展&#xff0c;很多前端工程师已经不满足于只做诸如页面布局和交互这些开发工作了&#xff0c;很多人将目光逐渐转向了“大前端”范围&#xff0c;其中就包括不…

Vim学习笔记【Ch03】

Vim学习笔记 系列笔记链接Ch03 Searching FilesVim中打开和编辑文件用Find进行文件搜索用grep进行文件内搜索:vim搜索:grep搜索 通过Netrw浏览文件Fzffzf和ripgrep安装fzf配置fzf语法查找文件在文件内部查找用Rg代替Grep在多个文件中搜索和替换 小结 系列笔记链接 Ch00&#x…

【论文速览】根据人脑fMRI信号重建图像 Image Reconstruction from human brain activity

文章目录 前言文章一研究背景主要方法部分实验结果总结与思考参考资料 文章二研究背景主要方法部分实验结果总结与思考 前言 人类的视觉神经系统对于真实世界的视觉刺激有着非凡的感知与理解能力&#xff0c;比如我们能够准确地识别物体距离和三维几何关系等&#xff0c;这是当…