内容简介:本系列文章将通过自己的一个开发工具库的实战经验(踩过的坑)教大家如何开发属于自己的一个工具库,在这里你可以学到Git的使用规范,基础项目的搭建,代码编写的规范,函数式编程思想,TypeScript实战,单元测试,编写文档和发布NPM包等等知识。阅读文章你可能需要以下基础知识:
本系列文章将通过自己的一个开发 工具 库的实战经验(踩过的坑)教大家如何开发属于自己的一个工具库,在这里你可以学到Git的使用规范,基础项目的搭建,代码编写的规范,函数式编程思想,TypeScript实战,单元测试,编写文档和发布NPM包等等知识。
阅读文章你可能需要以下基础知识:
- Git的基本使用
- TypeScript
- ES6
项目源码
系列目录
为什么要用函数式编程
因为函数式编程不会改变外部的变量,且对固定输入有唯一输出,这样我们可以不管函数内部的具体实现去使用它,而且可以很方便地通过组合多个函数而成我们想要的那个函数,更接近自然语言的表达。
比如我们要实现一个 y=f(x)=2*x+1 的函数,通常我们会这么写:
function f(x) {
return 2*x + 1;
}
f(1); // 3
复制代码
而函数式编程则是将他们拆分为几个小函数,再组装起来使用:
function double(x) {
return 2*x;
}
function plusOne(x) {
return x + 1;
}
plusOne(double(1)); // 3
// 或者还有更好一点的写法,这里暂未实现,
// 这里只是写下他们的调用方法,具体下面的文会讲到
const doubleThenPlusOne = compose(plusOne, double);
doubleThenPlusOne(1);
复制代码
纯函数
- 不可变性(immutable) 即对输入的实参及外部变量不能进行改变,没有副作用,以保证函数是“干净”的。
- 唯一性 对每个固定输入的参数,都有唯一对应的输出结果,有点类似于数学里的
y=f(x),当输入的x不变,输出的y也不会改变
这是一个栗子:
const array = [1, 9, 9, 6]; // slice是纯函数,因为它不会改变原数组,且对固定的输入有唯一的输出 array.slice(1, 2); // [9, 9] array.slice(1, 2); // [9, 9] // splice不是纯函数,它即改变原数组,且对固定输入,输出的结果也不同 array.splice(0, 1); // [9 ,9 ,6] array.splice(0, 1); // [9 ,6] 复制代码
柯里化(Currying)
柯里化就是传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。 我们上面实现了一个加一的函数,但当我们又需要一个加二的函数,又重新去写代码实现它的话效率是很低的,所以我们就需要柯里化,我们设想一下可不可以这样呢:
const plusOne = add(1); const plusTwo = add(2); plusOne(1); // 2 plusTwo(2); // 4 复制代码
这样我们就可以很容易地得到想要的函数,下面是 add 函数的实现:
function add(a) {
return function(b) {
return a + b;
}
}
复制代码
虽然基本满足我们现在的需求,但感觉还是不太方便,如果我们要实现三个或多个数的相加我们可能得这样写:
function add(a) {
return function(b) {
return function(c) {
return a + b + c;
}
}
}
复制代码
于是我们再设想一种更方便的方法:
function add(a, b, c) {
return a + b + c;
}
const curryAdd = curry(add);
const plusOne = curryAdd(1);
const plusOneAndTwo - curryAdd(1, 2);
plusOne(2, 3); // 6
plusOneAndTwo(3); // 6
curryAdd(1)(2, 3); // 6
curryAdd(1)(2)(3); // 6
复制代码
这样我们就可以自由产生需要参数不同的函数啦,下面是 curry 的实现方法(有兴趣的同学可以先思考下再看):
function curry<Return>(fn: Function): CurryFunction<Return> {
// 记录传进来的函数总共需要多少个参数
let paramsLength: number = fn.length;
function closure(params: any[]): CurryFunction<Return> {
let wrapper: CurryFunction<Return> = function (...newParams: any[]) {
// 将所有的参数取出
let allParams = [...params, ...newParams];
if (allParams.length < paramsLength) {
// 如果参数数量还不够则返回新的函数
return closure(allParams);
} else {
// 否则返回结果
return fn.apply(null, allParams);
}
};
return wrapper;
}
return closure([]);
}
复制代码
可能有些不太好理解,一时看不懂的同学可以先跳过这里看下面~
另外也可以用原生的 bind 函数来实现柯里化:
const plusOne = add.bind(null, 1); plusOne(2, 3); 复制代码
函数组合(Compose)
函数组合就是把多个不同的函数组合成一个新的函数。
比如这样:
// 将函数从右往左组合 const doubleThenPlusOne = compose(plusOne, double); // 1*2 + 1 doubleThenPlusOne(1); // 3 复制代码
function compose<Return>(...fn: any[]): (...params: any[]) => Return {
return (...params: any[]): Return => {
let i = fn.length - 1;
let result = fn[i].apply(null, params);
while (--i >= 0) {
result = fn[i](result);
}
return result;
};
}
复制代码
延迟输出
有时候这个世界并不是那么美好的,并不是所有的代码都是那么“干净”的,比如I/O操作和DOM操作这些等待,因为这些操作都对外部有依赖,会对外部有影响。这时候就需要用延迟输出来保证我们的函数是“干净”的,例如下面实现的这个 random 函数:
function random(min: number = 0, max: number, float: boolean): () => number {
return (): number => {
if (min > max) {
[min, max] = [max, min];
}
if (float || min % 1 || max % 1) {
return min + Math.random() * (max - min);
}
return min + Math.floor(Math.random() * (max - min + 1));
};
}
复制代码
对于固定的输入,它总返回的是产生符合条件的随机数的函数,这样我们就通过“拖延症”来让我们的代码保持“干净”啦,是不是很机智呢!这样做的好处还有它通过闭包机制把参数都记住,缓存起来,下次可以不用重复传同样的参数:
const createRandomNumber = random(1, 100, false); createRandomNumber(); createRandomNumber(); // 可以多次重复调用产生1到100随机数 复制代码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 前端笔记(关于箭头函数与普通函数的区别的理解)
- 前端Vue:函数式组件
- 前端面试ES6系列:箭头函数和普通函数的区别
- 函数劫持能做啥?前端黑科技揭秘
- 三角函数在前端动画中的应用
- 前端进击的巨人(四):略知函数式编程
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Algorithms + Data Structures = Programs
Niklaus Wirth / Prentice Hall / 1975-11-11 / GBP 84.95
It might seem completely dated with all its examples written in the now outmoded Pascal programming language (well, unless you are one of those Delphi zealot trying to resist to the Java/.NET dominanc......一起来看看 《Algorithms + Data Structures = Programs》 这本书的介绍吧!