相同的输入永远会得到相同的输出,而且没有任何可观察的副作用。
slice不会改变原数组 纯函数
splice会改变原数组 不纯函数
函数式编程不会保留计算中间的结果,所以变量是不可变的(无状态),PS:简单来讲反复使用相互不受影响
我们可以把一个函数的执行结果交 给另一个函数去处理
例如loadsh库:first、last、toUpper、reserve、each、include、find、finindex(后三种是es6之后出现的,返回的是boolean值)
纯函数的好处
`可缓存:因为纯函数对相同的输入始终有相同的结果,所以可以把纯函数的结果缓存起来。
//记忆函数
// const _ =require('lodash')
function getArea(r) {
console.log('打印');
return Math.PI *r *r
}
let getArea_ = _.memoize(getArea);
console.log(getArea_(4));
console.log(getArea_(4));
console.log(getArea_(4));
//模拟 memoize的实现
function memoize(f) {
let cache = {};
return function () {
let key = JSON.stringify(arguments);
cache[key] = cache[key] || f.apply(f,arguments);
return cache[key]
}
}let getArea_ = memoize(getArea);
console.log(getArea_(4));
console.log(getArea_(4));
console.log(getArea_(4));
可测试:纯函数让测试更方便
并行处理:
1)在多线程环境下并行操作共享的内存数据可能会出现意外的情况
2)纯函数不需要访问共享的内存数据,所以在并行环境下可以任意运行纯函数(web worker)PS:多线程下修改变量,在es6之后js可实现多线程处理
副作用
纯函数无副作用
副作用来源:
-配置文件
-全局变量出现在函数中(非纯函数)
-获取用户的输入
-其他
所有的外部交互都有可能产生副作用,使得方法的通用性下降不适合扩展和可重用性,同时副作用会给程序带来隐患和不确定性,但是副作用不可完全禁止,只能在尽可能的控制他们在控制范围内产生。
柯里化(Haskell Brroks Curry)
-当一个函数有多个参数的时候先传递一部分参数调用它(这部分参数永远不变)
-然后返回一个新的函数接收剩余的参数,返回结果
//柯里化演示
function checkAge(age) {
let min = 18;
return age>=min;
}
//上述函数缺点:有硬编码变量
//纯函数
function checkAge(min,age) {
return age>=min;
}
checkAge(18,16);
checkAge(18,25);
//上述函数缺点:基准值重复
//柯里化
function checkAge(min) {
return function (age) {
return age >=min;
}
}
//es6
let checkAge = min => (age => age >= min);
let checkAge18 =checkAge(18);
let checkAge28=checkAge(28);
console.log(checkAge18(20));
console.log(checkAge28(20));
loadash中的柯里化函数
-_.currry(func)
1)功能:创建一个函数,该函数接收一个或多个func的参数,如果func所需要的参数都被提供则执行func并返回执行的结果,否则继续返回该函数并等待接收剩余的参数。
示例:
const _ = require('lodash');
//形参多少个可称为几元函数,例如三个称为三元函数
function getSum(a,b,c) {
return a + b + c;
}
const curried = _.curry(getSum);
console.log(curried(1,2,3));
//只有部分参数,执行后返回一个参数等待剩余参数
console.log(curried(1)(2,3));
console.log(curried(1,2)(3));
2)参数:需要柯里化的函数
3)返回值:柯里化后的函数
demo:
//柯里化案例
// ''.match(/\s+/g)
const _ = require('lodash')
const match = _.curry(function(reg, str){
return str.match(reg)
})
const haveSpace = match(/\s+/g);
const haveNumber = match(/\d+/g);
// console.log(haveSpace("hello world"));
// console.log(haveNumber("123abc"));
const filter = _.curry(function(func,array){
return array.filter(func);
})
//箭头函数
const filter = _.curry((func,array) => array.filter(func));
console.log(filter(haveSpace,['sdf asdas']));
模拟柯里化curry
const _ = require('lodash');
//形参多少个可称为几元函数,例如三个称为三元函数
function getSum(a,b,c) {
return a + b + c;
}
const curried = _.curry(getSum);
const get1 = curried(1);
const get2 = curried(1,2);
const get3 = curried(3);
// console.log(get2(2));
function curry(func){
return function curriedFn(...args){
//判断实参和形参的个数
if(args.length < func.length){
return function(){//这里多套一层function,我理解为需要获取函数的arguments
return curriedFn(...args.concat(Array.from(arguments)))
}
}
return func(...args);
// return func.apply(func,arguments);
}
}
const curr = curry(getSum);
console.log(curr(1,2,3));
总结:
-柯里化可以让我们给一个函数传递较少的参数得到一个已经记住了某些固定参数的新函数
-这是一种对函数参数的缓存
-让函数变得更灵活,让函数的粒度更小
-可以把多元函数转换成一元函数,可以组合使用函数产生强大的功能