函数式编程
- 或称函数程序设计,又称泛函编程。它将电脑运算视为数学上的函数计算,比起命令式编程,函数式编程更加强调程序执行的结果而非执行的过程,倡导利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,而不是设计一个复杂的执行过程。
函数式基础
1.高阶函数
js 函数是一等对象,它可以赋给变量;可以作为参数传入其他函数
- 特点:接受一个函数作为参数,也可以传入其他参数,最后返回另一个函数。返回的函数通常会添加一些增强的功能。
- react 常用模式是使用高阶组件,将组件作为函数,并为它们增加一些常用行为。
(function () {
console.log('例子------>2.3.1');
const add = (x, y) => x + y;
const Log = fn => (...args) => { // 如果 Log 被调用 即产生一个闭包 fn , 保证fn成为私有功能,不被污染。
console.log(...args); // 框架搭建时候的 路由守卫 || 增强型的工具函数使用。
return fn(...args); // ES2015 解构
}
const AddLog = Log(add); // js工厂函数 创建一类 || 还有 new 的构造函数 使用的 不是return而是 this
console.log(AddLog(1, 2));
console.log('例子------>2.3.1 不用箭头函数');
function add1(x, y) {
return x + y;
}
function Log1(fn) {
return function () {
console.log(arguments); // 类对象, 不是真正的对象
// console.log(arguments.callee); // 函数本身, 用在递归调用
return fn(arguments[0], arguments[1]);
}
}
var AddLog1 = Log1(add1);
console.log(AddLog1(1, 2));
})();
2.纯粹性
- 纯函数: 不产生副作用,它自己不会改变自身作用域范围以外的任何东西。必重复使用,多是工具类。
- 非纯函数:改变上层作用域的变量 或者与DOM发生交互。不太可能多次调用它们,并期望得到相同结果。
(function () {
console.log('例子------>2.3.2');
const add = (x, y) => x + y;
let x = 1;
const add1 = y => (x += y);
console.log(add(1, 2));
console.log(add(1, 2));
console.log('纯函数如上----非纯函数如下');
console.log(add1(2));
console.log(add1(2));
})();
3.不可变性
- 函数入参,如果是非原始类型(引用类型的)很有可能改变原数据,导致多次调用产生副作用。如果我们需要主动 变量的值。
- 函数式编程中,函数不会修改变量值,而是创建新的变量,赋新值后再返回变量(cloneDeep || JS API 返回新对象)。
(function () {
console.log('例子------>2.3.3');
const add = (arr, str) => arr.push(str);
const myArr = [1, 2];
add(myArr, 'a1')
console.log(myArr);
add(myArr, 'a2')
console.log(myArr);
console.log('可变如上----不可变如下');
const add1 = (arr, str) => arr.concat(str); // concat API 自动返回一个新的数组。
const myArr1 = [1, 2];
console.log(add1(myArr1, 'a1'));
console.log(add1(myArr1, 'a2'));
console.log(myArr1);
})();
4.柯里化
- 函数式编程的常用技巧。柯里化过程是将多参数函数转化成单参数函数。
- 这些单参数函数的返回值也是函数
(function () {
console.log('例子------>2.3.4');
// 原有写法
const initAdd = (x, y) => x + y;
// 柯里化写法
const plus = x => y => x + y;
const plus5 = plus(5); // 起订量加5; 本地调用将x值 变成了内层函数的私有变量,闭包保护。
console.log(plus5(1));
console.log(plus5(2));
const plus7 = plus(7); // 进京证加7; 本地调用将x值 变成了内层函数的私有变量,闭包保护。
console.log(plus7(1));
console.log(plus7(2));
})();
5.组合
- 函数(和组件)可以结合产生新函数,从而提供更高级的功能和属性
(function () {
console.log('例子------>2.3.5');
const add = (x, y) => x + y;
const square = x => x * x;
// 组合
const addAndSquare = (x, y) => square(add(x, y));
// 遵循这种范式 我们可以编写小而简单、易于测试的纯函数、再将他们组合起来使用。
console.log(addAndSquare(1,2));
})();