函数式编程

75 阅读2分钟

一、函数式编程的出现

发展历程: 命令(脚本)式 => 面向对象式 => 函数式

1、面试题
   1、数组在url中展示的形式是什么?
   location.search = "?arr[]=code$%1&arr[]=code$%2&arr[]=code$%3"
   2、如何将字符串转换为数组?
   ['code$%1', 'code$%2', 'code$%3']
   3、转换成对象
   [{arr: 'code 1'}, {arr: 'code 2'}, {arr: 'code 3'}]

   const arr = ['code$%1', 'code$%2', 'code$%3'];
   const objArr = [];
   arr.forEach(item => {
      let newObj = item.split('$%')[0] + item.split('$%')[1];
      objArr.push({arr: newObj})
   })
   方法拆分:
   1、拆分字符串 => arr.split('$%')
   2、组装字符串并且首字母大写 => _objArr.map(item => {
      return item[0].toUpperCase() + item.slice(1)
   })
   3、组装对象 => objArr.map(item => {
      return {arr: item}
   })
 

二、函数式编程原理特点

1、函数式原理
  • 函数式编程的核心思想是:将函数作为参数传递给另一个函数,然后由另一个函数调用该函数,从而实现对数据的处理。
2、理论思想
函数(一等公民)=> 1、逻辑功能最终实现 2、实现函数 与 流程拼接
声明式编程 => 声明需求 - 更贴近语言习惯
惰性执行(惰性函数)=> 衔接型,性能节约 (惰性函数表示函数执行的分支只会在函数第一次调用的时候执行)
   const inertiaFn = val => {
      if(val == 'fn1') {
         return ineriaFn = () => {
            console.log('fn1')
         }
      }else if(val == 'fn2') {
         return ineriaFn = () => {
            console.log('fn2')
         }
      }else {
         return ineriaFn = () => {
            console.log('fn3')
         }
      }
   }
   inertiaFn('fn1')()
3、无状态与无副作用 -- 纯函数
  • 无状态:数据不可变 - 不可因为外界的调用而改变能力功能;
  • 无副作用:函数的内部不应该直接对整个系统中任何参数变量进行改动

三、实际开发

1、纯函数改造
   const _class = {
      name: 'code',
   }
   // 函数内部引入外部变量 -- 无状态
   const fn = (obj) => {_class.name + ':' + obj};
   // 直接修改输入参数 -- 无副作用
   const fn1 = (obj,name) => {obj.name = name};

   const fn2 = (obj,name) => {obj.name + ':' + name}; // 不依赖外部变量
   const fn3 = (obj,name) => ({...obj, name}); // 未修改外部变量

   fn2(_class, 'code');
   fn3(_class, 'code1');
2、流水线组装 - 加工 & 组装
加工 - 科里化
  • 科里化:将函数的参数进行拆分,将拆分后的函数进行组合,最终实现对函数的调用
   // fn(x,y,z) => fn(x)(y)(z)
   const sum = (x,y) => {
      return x + y
   }
   sum(1,2)
   const add = x => {
      return y => {
         return z => {
            return x + y + z
         }
      }
   }
   const add1 = add(1);
   add1(2)
   // 体系 = 加工 + 组装,单个加工输入输出应该单值化 => 单元函数
   const fetch = (methed ,url, params);

  • 面试题:手写构造可拆分传参的累加函数 add(1)(2)(3)(4)
   // 1、构造科里化的结构
   // 2、输入 处理外层 agruments => 类数组处理
   // 3、传入参数无限拓展 => 函数返回自身
   // 4、主功能 => 累加
   // 5、输出 支持从函数到产出转换
   const addd = function() {
      // let args = Array.prototype.slice.call(arguments)
      let args = [...arguments];
      let inner = function() {
         args.push(...arguments);
         return inner;
      }
      inner.toString = function() {
         return args.reduce((a,b) => a + b);
      }
      return inner;
   }
   addd(1)(2)(3)(4)