概念:
相同的输入永远得到相同的输出,而且没有任何可观察的副作用;
**
| 对比 | 纯函数 | 非纯函数 |
|---|---|---|
| 外部依赖 | 仅依赖入参 | 可能依赖全局变量,其他方法或者条件 |
| 输出 | 同样的输入,一样的输出 | 可能因为不同的情况,得到结果不同 |
| 对外影响 | 不改变原来的入参和环境内的变量等 | 可能会改变 |
案例
/*不是纯函数,因为同样的输入,输出结果不一致*/function a( count ){return count + Math.random();}/*不是纯函数,因为外部的 arr 被修改了*/function b( arr ){return arr.push(1);}let arr = [1, 2, 3];b(arr);console.log(arr); //[1, 2, 3, 1]/*不是纯函数,以为依赖了外部的 x*/let x = 1;function c( count ){return count + x;}
数组操作方法中的纯函数slice和非纯函数splice的举例
let arr = [1,2,3,4,5];// 纯函数 //不修改原数组console.log(arr.slice(0,3))console.log(arr.slice(0,3))console.log(arr.slice(0,3))// 不纯函数 原来的数组被修改console.log(arr.splice(0,3))console.log(arr.splice(0,3))console.log(arr.splice(0,3))
- 函数式编程,不会保留计算中间的结果,所以变量是不可变的(无状态的)
用处与优点:
1. 可缓存
定义:将上次的计算结果缓存起来,当下次调用时,如果遇到相同的参数,就直接返回缓存中的数据。
如果要实现以上功能,主要依靠 闭包 、柯里化、高阶函数let add = (a,b) => a+b;let calc = memoize(add);calc(10,20);//30calc(10,20);//30 缓存
实现原理:把参数和对应的结果数据存在一个对象中,调用时判断参数对应的数据是否存在,存在就返回对应的结果数据,否则就返回计算结果。
理论有了,我们来实现一个缓存函数: ```javascript function add(a,b){ console.log(‘执行计算’); return a+b; } const resolver = (…args)=>JSON.stringify(args);//获取args 转换成json字符串 function memoize(func,resolver){ let cache = {};//缓存对象,存放参数和结果的对应关系 return (…args)=>{
}const key = resolver(...args);if(cache[key]){ //如果key存在直接返回 对应的值return cache[key];}else{//不存在 则执行func的运算 并储存到keyreturn (cache[key] = func(...args))}
} const memoizeAdd = memoize(add,resolver); / console.log(memoizeAdd(1,2)); console.log(memoizeAdd(1,2)); console.log(memoizeAdd(1,2)); /
第二种写法```javascriptlet memoize = function (func, content) {let cache = Object.create(null)content = content || thisreturn (...key) => {if (!cache[key]) {cache[key] = func.apply(content, key)}return cache[key]}}
过程分析:
- 在当前函数作用域定义了一个空对象,用于缓存运行结果
- 运用柯里化返回一个函数,返回的函数因为作用域链的原因,可以访问到
cache - 然后判断输入参数是不是在
cache的中。如果已经存在,直接返回cache的内容,如果没有存在,使用函数func对输入参数求值,然后把结果存储在cache中。
在Vue中也有所体现
js/*** Create a cached version of a pure function.*/function cached (fn) {var cache = Object.create(null);return (function cachedFn (str) {var hit = cache[str];return hit || (cache[str] = fn(str))})}/*** Capitalize a string.*/var capitalize = cached(function (str) {return str.charAt(0).toUpperCase() + str.slice(1)});...capitalize(camelizedId)
适用场景:
- 需要大量重复计算
- 大量计算并且依赖之前的结果
**
2.可测试:纯函数让测试更方便
3.并行处理: 在多线程环境下并行操作共享的内存数据很可能出现意外情况;纯函数不需要访问共享的内存数据,所以在并行环境可以任意运行纯函数(web worker)
4.纯函数不需要访问共享的内存数据,所以在并行环境下可以任意运行纯函数
