如何实现JavaScript函数式的浅析

技术如何实现JavaScript函数式的浅析这篇文章给大家介绍如何实现JavaScript函数式的浅析,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。JS函数式浅析0x00 入门的导语(废话)最近两年

本文介绍了如何实现JavaScript函数分析。内容非常详细。感兴趣的朋友可以参考一下,希望对你有所帮助。

JS函数式浅析

0x00 入门的导语(废话)

最近两年,如果要说函数式编程不流行,那是不可能的,但是大家都知道函数式编程很流行。函数式编程为什么受欢迎,在于它的思想,非常强大!尤其是前端redux在reducer上完全使用纯函数,函数表达式的好处逐渐被发现。

常用函数库:

拉姆达设计了一个伟大的图书馆。

洛达什是一个普通的图书馆。

下划线也应该是一个很好的库。

0x01 纯函数

定义:相同的输入必须获得相同的输出,并且在操作过程中不修改或读取外部环境的变量的函数。

说出来很难理解,但还是要看代码。就好像不看国足比赛,你永远不知道为什么国足会输给月薪几百块的叙利亚。

//Array.slice必须是固定输入的固定输出,不依赖于外部变量。什么事?你依赖arr变量吗?//其实这个写法和Array.prototype.slice(arr,0,3)是一样的;是一样的。所以我理解。//你还学到了一件事:Array.slice不会修改原数组!vararr=[1,2,3,4,5];arr.slice(0,3);//Array.splice会修改xs,所以不纯,所以同样的输入不会有同样的输出!varxs.splice(0,3);//=[1,2,3]xs.splice(0,3);//=[4,5]xs.splice(0,3);//=[]纯函数:的好处。如果不修改外部变量,就不会有线程安全问题。它可以大大降低系统的复杂性。

0x02 函数的柯里化

你看!代码!

//调用doWht ('I ',' home ',' rice ');letdoWhat=(who,where,What)={ return What ' What }后的等效效果//cori ization in ' where '/Call doWhat(' I ')(' home ')(' meat ')Let do What=who=where=What={ return What ' do ' What } in ' where '至于我们不知道的,//tmp函数已经为我们保存了值,非常灵活。letdoWhatcurry=doWhat(' I ')(' home ')在上面提到的库中有一个名为curry的函数,可以将一个普通的函数进行corize。

0x03 函数的组合

函数组合是将函数组合起来生成一个新的函数。

//h(g(f(x))这是以前调用函数的方式。varadd1=x=x1varmul 5=x=x * 5//Compose将生成一个新函数,并将接收到的所有参数传递给add 1。

 然后add1的返回值传给mul5(注意注意!, mul5的参数个数只能有一个!!!), 然后compose生成的新的函数的返回值就是mul5的返回值. compose(mul5, add1)(2)

函数组合非常强大, 能够通过组合的方式来生成新的函数, 这是非常爽的. 如果你运用灵活, 会极大的减少你的代码量(如果不能减少别喷我啊),  compose的实现在上面提到的三个库中都有实现.

0x04 声明式与命令式风格

命令式的风格让我们通过代码引导机器, 让机器一步一步完成我们要的任务; 而声明式则是直接告诉机器我要做啥, 更直观.

//命令式 var persons = [...] for (var i = 0; persons.length; ++i) {   persons[i] = persons[i].toUppercase() }  //声明式 var persons = [...] persons.map(person => person.toUppercase())

0x05 Point free风格

// 假定如果  let map = fn => list => list.map(fn); let add = (a, b) => a + b;  // 函数incrementAll不是point free 风格 // 因为这里提到了numbers参数, 需要给出一个命名. // 这样定义函数会导致我们需要多命名一个变量. 麻烦! let incrementAll = (numbers) => map(add(1))(numbers);  // Point free风格的定义方法 // 假设add被柯里化过了 let incrementAll = map(add(1))

现在是推荐使用point free风格的代码(定义函数时), 这会减少我们不必要的命名. 多用这种风格哦!

0x06 容器(Functor)

容器代表了一个值, 一个任意值. 他就好像是函数式编程里的变量,函数的一个铠甲.可以让你的变量,函数在工程的战场中所向披靡!

var Container = function(x) {   this.__value = x; }  Container.of = x => new Container(x);  Container.prototype.map = function(f){   return Container.of(f(this.__value)) }  Container.of(3).map(x => x+1).map(x => x*5) // of用来构建容器, map用来变换容器 // Functor可以做很多很多事情, 具体的? 往下介绍.
// Maybe就是在普通容器上新增了一个检查空值的行为.  var Maybe = function(x) {   this.__value = x; }  Maybe.of = function(x) {   return new Maybe(x); }  Maybe.prototype.map = function(f) {   return this.isNothing() ? Maybe.of(null) : Maybe.of(f(this.__value)); }  Maybe.prototype.isNothing = function() {   return (this.__value === null || this.__value === undefined); }  // 例子, 如果name是空的话就会输出空了 var functor = Maybe.of({name: ‘mrcode'}) functor     .map(value => value.age)     .map(String.prototype.upperCase)     .map(value => console.log(value))

这个Maybe到底有啥用呢? 就是空值检测, 看上面的例子, 如果不进行判空的话,  第二个map就会调用String.prototype.upperCase函数, 会抛出异常的, 怕了吧? :P, 而且,  现在很多语言,swift等都添加了类似的支持. optional

Maybe只能判空, 但是Either才是真正的处理错误的容器, Either有两个子类, Left和Right.

// Promise是通过catch方法来接收错误的 如: doSomething()     .then(async1)     .then(async2)     .catch(e => console.log(e));  // 完全一样     var Left = function(x) {   this.__value = x; } var Right = function(x) {   this.__value = x; }  // 完全一样 Left.of = function(x) {   return new Left(x); } Right.of = function(x) {   return new Right(x); }  // 这里不同!!! Left.prototype.map = function(f) {   return this; } Right.prototype.map = function(f) {   return Right.of(f(this.__value)); }  // 应用: var getAge = user => user.age ? Right.of(user.age) : Left.of("ERROR!") getAge({name: 'stark', age: '21'}).map(age => 'Age is ' + age); //=> Right('Age is 21')  getAge({name: 'stark'}).map(age => 'Age is ' + age); //=> Left('ERROR!')

Left会跳过所有执行过程, 直达结果, 这就好像Right是流程图里一个又一个指向下一个任务的箭头, 而Left直接指向了结果, 是错误的结果.

0x07 IO

诶, 函数式编程里, 涉及到IO总是让人尴尬的, 蓝瘦的很..幸好, 有一种叫做IO的东西专门处理IO这种东西(别嫌绕哈), 看代码,

// 没毛病 var IO = function(f) {     this.__value = f; }  // ??? 看不懂, 待会解释.. IO.of = x => new IO(_ => x);  // ??? 这是啥子鬼???? IO.prototype.map = function(f) {     return new IO(compose(f, this.__value)) };

权威解答: 这里的IO里存的是一个函数, 包裹了外部环境变量的函数, 我们传入了一个函数, 这个函数里包含了实际的值,会进行IO操作.  我们把不纯的IO操作放到了这个函数里, 总体上看, 我们的IO对象, 是不会执行这些不纯的操作的. 它依然是纯的, 因为IO操作压根就没执行内部包含的函数,  这个函数是外部调用者去执行的. 也就是说, 不纯的操作是外部的人干的, 和我们的IO对象一丢丢关系都木有!(干得漂亮!) 看一个例子.

var io_document = new IO(_ => window.document); io_document.map(function(doc){ return doc.title }); // 得到IO(documen.title)

科普: 这里你没有得到document.title, 你得到的仅仅是一个会返回document.title的一个函数, 这个函数是不纯的,  但是执行不是由上面的代码执行的, 锅在调用函数的人身上! 上面的代码依然是'纯'的!

0x08 Monad

看这个部分的时候建议看一下IO的实现, 好好理解一下, 我知道有点烧脑, 但是看一下没坏处!玩过Promise的都知道,  Promise.then传进去的函数可以返回一个新的Promise. Promise就是Monad.

0x09 函数式编程的应用

react中的纯组件

// 固定的输入得到固定的输出 纯组件极大的增加了react的灵活程度 // app 的状态交给一些状态机管理 比如redux var Text = props => (     <div style={props.style}>{props.text}</div> )

redux中的reducer

// 输入当前状态和action, 输出nowState reducer(currentState, action) => newState

0x10 总结一下

确实是这样, 不总结的话就不像是一篇文章了, 还是总结下吧:

  • 纯函数的概念以及函数柯里化和函数的组合

  • 容器概念, Container和Maybe, Either的派生Left,Right, IO作用.

  • 函数式编程的应用

关于如何实现JavaScript函数式的浅析就分享到这里了,希望

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/97013.html

(0)

相关推荐

  • MySQL 5.7怎么升级到8.0

    技术MySQL 5.7怎么升级到8.0这篇文章主要讲解了“MySQL 5.7怎么升级到8.0”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“MySQL 5.7怎么升级到8.

    攻略 2021年11月12日
  • 编译时JAVA最常见的错误是什么

    技术编译时JAVA最常见的错误是什么本篇内容主要讲解“编译时JAVA最常见的错误是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“编译时JAVA最常见的错误是什么”吧!  

    攻略 2021年11月2日
  • linux进程调度采用的是什么(linux进程调度详解)

    技术linux进程调度源码是什么这篇文章主要讲解了“linux进程调度源码是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“linux进程调度源码是什么”吧!下面是进程

    攻略 2021年12月17日
  • 如何理解jmeter

    技术如何理解jmeter今天就跟大家聊聊有关如何理解jmeter,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。 1. jmeter环境

    攻略 2021年11月17日
  • Python中如何实现Scrapy+adbapi提高数据库写入效率

    技术Python中如何实现Scrapy+adbapi提高数据库写入效率今天就跟大家聊聊有关Python中如何实现Scrapy+adbapi提高数据库写入效率,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下

    攻略 2021年10月21日
  • spring cloud gateway支持contextPath分析

    技术spring cloud gateway支持contextPath分析本篇内容主要讲解“spring cloud gateway支持contextPath分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实

    攻略 2021年11月17日