概念:

相同的输入永远得到相同的输出,而且没有任何可观察的副作用;
**

对比 纯函数 非纯函数
外部依赖 仅依赖入参 可能依赖全局变量,其他方法或者条件
输出 同样的输入,一样的输出 可能因为不同的情况,得到结果不同
对外影响 不改变原来的入参和环境内的变量等 可能会改变

案例

  1. /*不是纯函数,因为同样的输入,输出结果不一致*/
  2. function a( count ){
  3. return count + Math.random();
  4. }
  5. /*不是纯函数,因为外部的 arr 被修改了*/
  6. function b( arr ){
  7. return arr.push(1);
  8. }
  9. let arr = [1, 2, 3];
  10. b(arr);
  11. console.log(arr); //[1, 2, 3, 1]
  12. /*不是纯函数,以为依赖了外部的 x*/
  13. let x = 1;
  14. function c( count ){
  15. return count + x;
  16. }

数组操作方法中的纯函数slice和非纯函数splice的举例

  1. let arr = [1,2,3,4,5];
  2. // 纯函数 //不修改原数组
  3. console.log(arr.slice(0,3))
  4. console.log(arr.slice(0,3))
  5. console.log(arr.slice(0,3))
  6. // 不纯函数 原来的数组被修改
  7. console.log(arr.splice(0,3))
  8. console.log(arr.splice(0,3))
  9. console.log(arr.splice(0,3))
  • 函数式编程,不会保留计算中间的结果,所以变量是不可变的(无状态的)

    用处与优点:

    1. 可缓存
    定义:将上次的计算结果缓存起来,当下次调用时,如果遇到相同的参数,就直接返回缓存中的数据。

    1. let add = (a,b) => a+b;
    2. let calc = memoize(add);
    3. calc(10,20);//30
    4. calc(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)=>{
    1. const key = resolver(...args);
    2. if(cache[key]){ //如果key存在直接返回 对应的值
    3. return cache[key];
    4. }else{//不存在 则执行func的运算 并储存到key
    5. return (cache[key] = func(...args))
    6. }
    }

} const memoizeAdd = memoize(add,resolver); / console.log(memoizeAdd(1,2)); console.log(memoizeAdd(1,2)); console.log(memoizeAdd(1,2)); /

  1. 第二种写法
  2. ```javascript
  3. let memoize = function (func, content) {
  4. let cache = Object.create(null)
  5. content = content || this
  6. return (...key) => {
  7. if (!cache[key]) {
  8. cache[key] = func.apply(content, key)
  9. }
  10. return cache[key]
  11. }
  12. }

过程分析:

  • 在当前函数作用域定义了一个空对象,用于缓存运行结果
  • 运用柯里化返回一个函数,返回的函数因为作用域链的原因,可以访问到cache
  • 然后判断输入参数是不是在cache的中。如果已经存在,直接返回cache的内容,如果没有存在,使用函数func对输入参数求值,然后把结果存储在cache中。

在Vue中也有所体现

  1. js/**
  2. * Create a cached version of a pure function.
  3. */
  4. function cached (fn) {
  5. var cache = Object.create(null);
  6. return (function cachedFn (str) {
  7. var hit = cache[str];
  8. return hit || (cache[str] = fn(str))
  9. })
  10. }
  11. /**
  12. * Capitalize a string.
  13. */
  14. var capitalize = cached(function (str) {
  15. return str.charAt(0).toUpperCase() + str.slice(1)
  16. });
  17. ...
  18. capitalize(camelizedId)

适用场景:

  • 需要大量重复计算
  • 大量计算并且依赖之前的结果

**
2.可测试:纯函数让测试更方便
3.并行处理: 在多线程环境下并行操作共享的内存数据很可能出现意外情况;纯函数不需要访问共享的内存数据,所以在并行环境可以任意运行纯函数(web worker)
4.纯函数不需要访问共享的内存数据,所以在并行环境下可以任意运行纯函数