前
前
前端内参
搜索文档…
前端内参
零.0.1 前言·写给有缘人
零、准备Hard模式下的面试
零.1.1 一线互联网公司有什么不同?
零.1.2 该公司是做什么的,实力怎么样,前景如何,口碑怎样?
零.1.3 该岗位负责做什么的,岗位所属部门在什么位置,上升空间多大?
零.1.4 准备一份好的简历
零.1.5 不卑不亢,不疾不徐地说话
零.1.6 “有什么问题要问我吗”,如何回答?
壹、前端之灵:JavaScript/ECMAScript
壹.1.1 新版 ECMAScript 特性分析
壹.1.2 JavaScript未来的方向
壹.2.1 函数
壹.2.2 作用域、执行上下文、作用域链
壹.2.3 彻底搞懂 this
壹.2.4 深入理解 call、apply、bind
壹.2.5 面试时高频问到的“闭包”
壹.2.6 原型和原型链
壹.2.7 同步和异步,阻塞和非阻塞
壹.2.8 Event Loop
壹.2.9 强大的数组
壹.2.10 正则表达式
壹.2.11 位操作符与进制转换
壹.2.12 spread和rest操作符
壹.2.13 实现异步非阻塞的任务
壹.2.14 模块化开发
壹.3.1 深拷贝与浅拷贝
壹.3.2 JavaScript函数柯里化
壹.3.3 JavaScript元编程:Proxy与Reflect
壹.3.4 JavaScript中的进程、线程、协程
壹.4.2 页面重排(Reflow)与重绘(Repaint)
壹.4.3 DOM、Shadow DOM、Virtual DOM
壹.5.2 了解TCP、UDP、TLS
壹.5.3 Http几个版本的区别
壹.5.4 Http和Https的区别在哪里
壹.5.5 XSS与CSRF攻击
贰、数据结构与算法
贰.0 本章导读
贰.1.1 十大排序算法
贰.1.2 链表
贰.1.3 单调栈
贰.1.4 二叉树的遍历
贰.1.5 实战:字节跳动前端面试2道算法题
贰.1.6 分治法、动态规划与贪心算法的区别
贰.1.7 实战:阿里巴巴前端面试题
叁、主流框架/库
叁.1.1 jQuery过时了吗?
叁.1.2 React、Vue和Angular对比
叁.2.1 React Hooks究竟是什么?
肆、必会的工具
肆.1.1 深入理解Webpack打包
肆.3.2 适用于前端开发者的20个VSCode插件
伍、编程范式
伍.1.1 面向对象与面向过程有什么区别?
伍.1.3 重新认识JavaScript面向对象: 继承
伍.1.4 彻底搞懂泛型
伍.1.5 用JavaScript实现抽象类
伍.1.6 用JavaScript实现接口
伍.2.1 什么是函数式编程?
伍.2.2 JavaScript的函数式编程探索
伍.2.3 Pointfree无参数风格编程
伍.3.1 什么是响应式编程?
伍.3.2 RxJS
陆、设计原则与编程范式
陆.1.0 导读:SOLID
陆.1.1 单一职责原则
陆.1.2 接口隔离原则
陆.1.3 开放封闭原则
陆.1.4 里氏替换原则
陆.1.5 依赖倒置原则
柒 、设计模式与软件工程
柒.1.5 发布-订阅模式
柒.1.14 适配器模式
柒.2.1 MVC的前世今生
玖、公众号&博客推荐
玖.1 一线互联网公司前端团队官方公众号
玖.2 知名前端人物
拾、后记
拾.1 成为一个好的程序员远比找份好工作重要
拾.2 2020年前端技术展望
由
GitBook
提供支持
伍.2.2 JavaScript的函数式编程探索
上一篇
讲了函数式编程的理论知识,本篇探索一下JavaScript如何进行函数式编程。
01.Ramda,一款实用的 JavaScript 函数式编程库
工欲善其事必先利其器,JavaScript函数式编程怎能没有库这种利器!
Ramda
是一个非常适合函数式编程的函数库。函数库类似的有
lodash
。
lodash已经很成熟了,提供了足够好用的函数,那为什么还要Ramda呢?笔者认为:Ramda的理念更适合函数式编程。
Ramda的理念是:
Function first,data last.
也即函数优先,数据靠后。体现在具体的用法区别上,就是lodash会把第一个参数当成要处理的数据,函数等放在第一个参数之后传进来。而Ramda会把要出来的数据放在最后一个参数,最后一个参数之前的参数,都是传入的函数。
const
list
=
[{
a
:
1
},
{
a
:
2
},
{
a
:
3
}];
//lodash:数据在前
_
.
findIndex
(
list
,
(
o
)
=>
o
.
a
==
2
);
//>> 0
//Ramda:数据在最末尾
R
.
findIndex
(
R
.
propEq
(
'a'
,
2
),
list
);
//>> 1
将数据放在后面有什么好处呢?
好处是写的代码更精简,更方便阅读理解。这点结合Ramda的柯里化会感受更加明显。
02.Ramda的函数都是柯里化的
上面的代码第8行,可以写成:
R
.
findIndex
(
R
.
propEq
(
'a'
,
2
))(
list
);
//>> 1
也是可以的,这不就是柯里化形态吗。没错,而Ramda提供的所有函数都是已经柯里化的,这可以从源代码找到证据。看看最简单的
add函数
的源代码:
import
_curry2
from
'./internal/_curry2'
;
/**
* Adds two values.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Math
* @sig Number -> Number -> Number
* @param {Number} a
* @param {Number} b
* @return {Number}
* @see R.subtract
* @example
*
* R.add(2, 3); //=> 5
* R.add(7)(10); //=> 17
*/
var
add
=
_curry2
(
function
add
(
a
,
b
)
{
return
Number
(
a
)
+
Number
(
b
);
});
export
default
add
;
上面代码第1行就引入了
_curry2
这个内部函数,然后第21行调用
_curry2
将
add
函数柯里化。Ramda每个对外的函数,都这样处理过。因此Ramda对外提供的每个函数都是柯里化过的。
全部柯里化的目的是什么呢?
仍然是为了与前面讲述的“将数据放在末尾”结合使用,以便体现代码的简洁、可读性。
现在举例说明:求列表中a的值大于1的项,然后取各项值之和。
const
list
=
[{
a
:
1
},
{
a
:
2
},
{
a
:
3
}];
//lodash
{
//根据给定的列表求和
let
sum
=
data
=>
_
.
reduce
(
data
,
(
a
,
b
)
=>
a
+
b
.
a
,
0
);
//得到值>1的项组成的列表
let
getList
=
data
=>
_
.
filter
(
data
,
(
o
)
=>
o
.
a
>
1
);
let
total
=
_
.
flow
(
getList
,
sum
)(
list
);
console
.
log
(
total
);
//>> 5
}
//Ramda
{
let
sum
=
data
=>
R
.
reduce
((
a
,
b
)
=>
a
+
b
.
a
,
0
,
data
);
let
getList
=
data
=>
R
.
filter
((
o
)
=>
o
.
a
>
1
,
data
);
let
total
=
R
.
compose
(
sum
,
getList
)(
list
);
console
.
log
(
total
);
//>> 5
}
这样可能还看不出明显差别,别急,因为Ramda提供的函数都是柯里化过的,柯里化可以将多参数函数拆分成单参数函数,于是可以改成如下:
let
sum
=
data
=>
R
.
reduce
((
a
,
b
)
=>
a
+
b
.
a
,
0
)(
data
);
let
getList
=
data
=>
R
.
filter
((
o
)
=>
o
.
a
>
1
)(
data
);
let
total
=
R
.
compose
(
sum
,
getList
)(
list
);
console
.
log
(
total
);
//>> 5
基本可以发现一个Ramda代码的特征:第1、2行代码,作为数据的参数
data
固定地出现在参数和最末尾位置。既然第1,2行代码都有传数据参数
data
,而第3行代码传数据参数
list
,重复这么多次没有必要,同样是将数据以参数传递,笔者直觉这种情况出现一次就够了(理论上,
代码里有重复的地方都可以优化,出现一次就够
)。
那第1、2行多余的参数传递可以优化掉!因为末尾都是数据,那可以十分方便地优化掉(拿走就行了,比将数据放在最开头的参数位置而言,要方便得多)。再因为Ramda提供的函数都是柯里化过的,柯里化可以
延迟运行
,也即可以暂时不用传数据进来,在真正需要运行函数的时候传数据进来就可以了。所以,代码优化如下:
let
sum
=
R
.
reduce
((
a
,
b
)
=>
a
+
b
.
a
,
0
);
//优化掉data
let
getList
=
R
.
filter
((
o
)
=>
o
.
a
>
1
);
//优化掉data
let
total
=
R
.
compose
(
sum
,
getList
)(
list
);
//最后再统一传参data
console
.
log
(
total
);
//>> 5
哇!上面代码中第1、2行原本需要传递的参数
data
不见了,效果却一样!居然可以没
data
什么事?!的确可以!很清爽的代码。至此,就引出了一种无参数的编程风格:
Pointfree
,放在
下一篇
单独介绍。
可以发现正是因为Ramda把数据放在参数的最后一个位置,同时每个函数都柯里化过,因此能够省略一些参数,代码才变得更简洁,更易读。
参考文献
The Philosophy of Ramda
伍、编程范式 - 以前
伍.2.1 什么是函数式编程?
下一个 - 伍、编程范式
伍.2.3 Pointfree无参数风格编程
最近更新
1yr ago
复制链接
大纲
01.Ramda,一款实用的 JavaScript 函数式编程库
将数据放在后面有什么好处呢?
02.Ramda的函数都是柯里化的
全部柯里化的目的是什么呢?
参考文献