JS高级——纯函数、柯里化(手写自动柯里化函数)、组合函数(手写自动组合函数)

一、理解JavaScript纯函数

函数式编程中有一个非常重要的概念叫纯函数,JavaScript符合函数式编程的范式,所以也有纯函数的概念;

  • 在react开发中纯函数是被多次提及的;
  • 比如react中组件就被要求像是一个纯函数(为什么是像,因为还有class组件),redux中有一个reducer的概念,也是要求必须是一个纯函数;
  • 所以掌握纯函数对于理解很多框架的设计是非常有帮助的;

简单总结一下纯函数的定义:

  • 确定的输入,一定会产生确定的输出;
  • 函数在执行过程中,不能产生副作用;

副作用的理解

  • 副作用(side effect)其实本身是医学的一个概念,比如我们经常说吃什么药本来是为了治病,可能会产生一些其他的副作用;
  • 在计算机科学中,也引用了副作用的概念,表示在执行一个函数时,除了返回函数值之外,还对调用函数产生了附加的影响,比如修改了全局变量修改参数或者改变外部的存储

纯函数在执行的过程中就是不能产生这样的副作用:

  • 副作用往往是产生bug的 “温床”。

纯函数的案例

我们来看一个对数组操作的两个函数:

  • slice:slice截取数组时不会对原数组进行任何操作,而是生成一个新的数组;
  • splice:splice截取数组, 会返回一个新的数组, 也会对原数组进行修改
  • slice就是一个纯函数,不会修改传入的参数;
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

纯函数的优势

为什么纯函数在函数式编程中非常重要呢?

  • 因为你可以安心的编写和安心的使用;
  • 你在写的时候保证了函数的纯度,只是单纯实现自己的业务逻辑即可,不需要关心传入的内容是如何获得的或者依赖其他的外部变量是否已经发生了修改;
  • 你在用的时候,你确定你的输入内容不会被任意篡改,并且自己确定的输入,一定会有确定的输出;

React中就要求我们无论是函数还是class声明一个组件,这个组件都必须像纯函数一样,保护它们的props不被修改:
在这里插入图片描述

二、JavaScript柯里化

柯里化也是属于函数式编程里面一个非常重要的概念。

柯里化定义总结:

  • 只传递给函数一部分参数来调用它,让它返回一个函数去处理剩余的参数;
  • 这个过程就称之为柯里化;

柯里化的结构

那么柯里化到底是怎么样的表现呢?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

为什么需要有柯里化呢?

  1. 让函数的职责单一
  2. 复用参数逻辑
让函数的职责单一:
  • 在函数式编程中,我们其实往往希望一个函数处理的问题尽可能的单一,而不是将一大堆的处理过程交给一个函数来处理;
  • 那么我们就可以将每次传入的参数在单一的函数中进行处理,处理完后在下一个函数中再使用处理后的结果;

比如上面的案例我们进行一个修改:传入的函数需要分别被进行如下处理

  • 第一个参数 + 2
  • 第二个参数 * 2
  • 第三个参数 ** 2

在这里插入图片描述

在这里插入图片描述

复用参数逻辑:
  • makeAdder函数要求我们传入一个count(并且如果我们需要的话,可以在这里对count进行一些修改);
  • 在之后使用返回的函数时,我们不需要再继续传入count了
    在这里插入图片描述
    这里我们在演示一个案例,需求是打印一些日志:
  • 日志包括时间、类型、信息;
    在这里插入图片描述

三、手写自动柯里化函数

在这里插入图片描述

调用myCurrying函数即可将普通的函数,转成柯里化后的函数:
在这里插入图片描述

function sum(num1, num2, num3) {return num1 + num2 + num3
}
const res = sum(10, 20, 30)
console.log(res)// function sum(num1) {
//     return function (num2) {
//         return function (num3) {
//             return num1 + num2 + num3
//         }
//     }
// }
// console.log(sum(10)(20)(30))function myCurrying(fn) {return function curried(...args) {if (args.length >= fn.length) {// 如果当前curried函数传递的参数个数(args.length)>=需要变成柯里化函数(fn)的参数的个数// 符合:currySum(10, 20, 30), 则直接调用fn执行函数即可return fn.apply(this, args)} else {// 如果当前curried函数传递的参数个数<需要变成柯里化函数(sum)的参数的个数// 则需要继续返回一个函数来继续接收剩余的参数return function (...args2) {// 接收道参数后,需要递归调用curried来检查当前传入的参数个数是否达到原始函数fn的参数个数return curried.apply(this, [...args, ...args2])}}}
}const currySum = myCurrying(sum)
console.log(currySum(10, 20, 30))
console.log(currySum(10, 20)(30))
console.log(currySum(10)(20, 30))
console.log(currySum(10)(20)(30))

四、理解组合函数

组合(Compose)函数是在JavaScript开发过程中一种对函数的使用技巧、模式:

  • 比如我们现在需要对某一个数据进行函数的调用,执行两个函数fn1和fn2,这两个函数是依次执行的;
  • 那么如果每次我们都需要进行两个函数的调用,操作上就会显得重复;
  • 那么是否可以将这两个函数组合起来,自动依次调用呢?
  • 这个过程就是对函数的组合,我们称之为 组合函数(Compose Function);

在这里插入图片描述

手写自动组合函数:

刚才我们实现的compose函数比较简单,我们需要考虑更加复杂的情况:比如传入了更多的函数,在调用compose函数时,传入了更多的参数:
在这里插入图片描述

在这里插入图片描述

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

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

相关文章

三包围结构的字是什么样的_拼音带kun的字大全_50个拼音含kun的字组词

原标题&#xff1a;拼音带kun的字大全_50个拼音含kun的字组词1、昆(kūn)&#xff0c;8画&#xff0c;上下结构&#xff0c;部首&#xff1a;曰(日)组词&#xff1a;昆虫(kūn chng) | 昆曲(kūn qǔ) | 昆山(kūn shān) | 昆仲(kūn zhng) | 昆吾(kūn w) | 昆仑(kūn ln) |2…

JS高级——with语句、eval函数、严格模式

一、with语句 with语句的作用&#xff1a;扩展一个语句的作用域链。 不建议使用with语句&#xff0c;因为它可能是混淆错误和兼容性问题的根源。并且&#xff0c;在浏览器开启严格模式下&#xff0c;使用with会报错&#xff1a; 二、eval函数 eval是一个特殊的函数&#x…

JS面向对象——Object.defineProperty

一、JavaScript的面向对象 JavaScript其实支持多种编程范式的&#xff0c;包括函数式编程和面向对象编程&#xff1a; JavaScript中的对象被设计成一组属性的无序集合&#xff0c;像是一个哈希表&#xff0c;有key和value组成&#xff1b;key是一个标识符名称&#xff0c;val…

json字符串和字典类型的相互转换(转载)

转自&#xff1a;http://www.cnblogs.com/YUTOUYUWEI/p/5585863.html 在开发过程中&#xff0c;有时候需要将json字符串转为字典类型&#xff0c;反之亦然&#xff0c;通常采用.Net的开源类库Newtonsoft.Json进行序列化&#xff0c;这里我也是采用这个&#xff0c;不过我更喜欢…

JS高级——对象的原型__proto__、函数的原型prototype、构造函数

一、认识构造函数 我们先理解什么是构造函数&#xff1f; 构造函数也称之为构造器&#xff08;constructor&#xff09;&#xff0c;通常是我们在创建对象时会调用的函数&#xff1b;在其他面向的编程语言里面&#xff0c;构造函数是存在于类中的一个方法&#xff0c;称之为构造…

JS面向对象——原型链、通过原型链实现继承、借用构造函数实现继承

一、JavaScript原型链 在真正实现继承之前&#xff0c;我们先来理解一个非常重要的概念&#xff1a;原型链。 我们知道&#xff0c;从一个对象上获取属性&#xff0c;如果在当前对象中没有获取到就会去它的原型&#xff08;__proto__&#xff09;上面获取&#xff1a; 二、…

JS面向对象——原型式继承函数、寄生式继承函数、寄生组合式继承

一、原型式继承函数 回顾一下JavaScript想实现继承的目的&#xff1a;重复利用另外一个对象的属性和方法. 最终的目的&#xff1a;student对象的原型指向了person对象&#xff1b; 二、寄生式继承函数 寄生式(Parasitic)继承是与原型式继承紧密相关的一种思想, 并且同样由道格…

JS面向对象——Object对象的方法补充、原型继承关系图

一、Object.create() 这个方法用于创建一个新对象。被创建的对象的__proto__指向create函数第一个参数的原型对象prototype&#xff0c;在创建新对象时可以通过create函数第二个参数指定一些属性。 二、Object.hasOwnProperty() 对象是否有某一个属于自己的属性&#xff08…

JS面向对象——class定义类、类的构造函数、实例方法、访问器方法、静态方法、继承、super、多态

一、认识class定义类 我们会发现&#xff0c;按照前面的构造函数形式创建 类&#xff0c;不仅仅和编写普通的函数过于相似&#xff0c;而且代码并不容易理解。 在ES6&#xff08;ECMAScript2015&#xff09;新的标准中使用了class关键字来直接定义类&#xff1b;但是类本质上依…

ES6(一)——字面量的增强、解构、let/const、块级作用域、暂时性死区

一、字面量的增强 ES6中对 对象字面量 进行了增强&#xff0c;称之为 Enhanced object literals&#xff08;增强对象字面量&#xff09;。 字面量的增强主要包括下面几部分&#xff1a; 属性的简写&#xff1a;Property Shorthand方法的简写&#xff1a;Method Shorthand计算…

MapReduce算法形式四:mapjoin

案例四&#xff1a;mapjoin&#xff08;对个map共同输入&#xff0c;一个reduce&#xff09; 这个方法主要解决的是&#xff0c;几个表之间的比较&#xff0c;类似于数据库的内外连接&#xff0c;还有一些左右连接之类的&#xff0c;简而言之就是&#xff0c;A表没有的B表有&am…

ES6(二)——字符串模板、标签模板字符串、函数的默认参数、剩余参数、数组对象的展开语法、数值的表示、Symbol

一、字符串模板基本使用 在ES6之前&#xff0c;如果我们想要将字符串和一些动态的变量&#xff08;标识符&#xff09;拼接到一起&#xff0c;是非常麻烦和丑陋的&#xff08;ugly&#xff09;。 ES6允许我们使用字符串模板来嵌入JS的变量或者表达式来进行拼接&#xff1a; 首…

ES6(三)——Set、WeakSet、Map、WeakMap

一、Set的基本使用 在ES6之前&#xff0c;我们存储数据的结构主要有两种&#xff1a;数组、对象。 在ES6中新增了另外两种数据结构&#xff1a;Set、Map&#xff0c;以及它们的另外形式WeakSet、WeakMap。 Set是一个新增的数据结构&#xff0c;可以用来保存数据&#xff0c;类…

ES6~ES12——Array Includes、Object values、Object entries、Object fromEntries、flat、flatMap、空值合并运算符、可选链等

一、ES7 - Array Includes 在ES7之前&#xff0c;如果我们想判断一个数组中是否包含某个元素&#xff0c;需要通过 indexOf 获取结果&#xff0c;并且判断是否为 -1。 在ES7中&#xff0c;我们可以通过includes来判断一个数组中是否包含一个指定的元素&#xff0c;根据情况&…

移除通知的时机

链接 结论 最好是在不需要的时候就移除掉。 如果不是特别苛刻&#xff0c;可以直接在dealloc函数里写。因为dealloc函数一定会被调用的。 在dealloc函数中移除的可能问题 由于dealloc在Runloop结束时会被调用。如果在Runloop调用之前&#xff0c;又有一个通知到来&#xff0c;会…

JS高级——Proxy、Reflect

一、监听对象的操作 我们先来看一个需求&#xff1a;有一个对象&#xff0c;我们希望监听这个对象中的属性被设置或获取的过程 通过我们前面所学的知识&#xff0c;能不能做到这一点呢&#xff1f;其实是可以的&#xff0c;我们可以通过之前的属性描述符中的存储属性描述符来…

Promise学习笔记

一、异步任务的处理 这里我从一个实际的例子来作为切入点&#xff1a; 我们调用一个函数&#xff0c;这个函数中发送网络请求&#xff08;我们可以用定时器来模拟&#xff09;&#xff1b;如果发送网络请求成功了&#xff0c;那么告知调用者发送成功&#xff0c;并且将相关数…

JS高级——Iterator迭代器、Generator生成器

一、什么是迭代器&#xff1f; 在JavaScript中&#xff0c;迭代器也是一个具体的对象&#xff0c;这个对象需要符合迭代器协议&#xff08;iterator protocol&#xff09;&#xff1a; 迭代器协议定义了产生一系列值&#xff08;无论是有限还是无限个&#xff09;的标准方式&…

删除一行下方单元格上移_快速删除Excel工作表多余空单元格

从其他地方复制了数据&#xff0c;有时候会出现多余的空单元格。手动删除很麻烦&#xff0c;就像下面的图中的工作表区域。下面介绍一种方法&#xff0c;可以快速删除多余空单元格。1.选中目标区域&#xff0c;在这里就选中A1:A9的单元格区域。2.按键盘上的F5或者CtrlG。3.点击…

JS高级——await-async

一、异步函数 async function async关键字用于声明一个异步函数&#xff1a; async是asynchronous单词的缩写&#xff0c;异步、非同步&#xff1b;sync是synchronous单词的缩写&#xff0c;同步、同时&#xff1b; async异步函数可以有很多中写法&#xff1a; 二、异步函…