提升代码的可靠性之函数式编程

676 阅读2分钟

函数式编程

假如目前有一个需求,把数组的每一项+1

1.初级程序员的写法

 let arr = [1,2,3,4];
    let newArr = []
    for(let i = 0; i< arr.length; i++) {
      newArr.push(arr[i] + 1)
    }

2.好一点的程序员的写法

 let newArr = (arr) => {
      let res = [];
      arr.map((item) => {
        res.push(item + 1)
      })

      return res;
    }
    newArr(arr);

但是这两种写法都是命令式编程不是灵活的写法,代码是不能复用的,当需求变更之后,代码就需要改动,重复的事情需要多次操作。 所以在代码书写过程中,使用函数式编程是一种更好一些的方式。

 let arr = [1,2,3,4]
    let newArr = (arr, fn) => {
      let res = [];
      for(let i = 0; i < arr.length; i++) {
        res.push(fn(arr[i]));
      }
      return res;
    }

    let add = (item) => item + 5;
    let sum = newArr(arr, add);

采用函数式编程的方式可以很方便的用来获取不同需求的结果,例如乘法,减法等

纯函数

如果函数的调用参数相同,会永远返回相同的结果,它不依赖程序执行期间函数外部任何状态或者数据的变化,只依赖其输入的参数

let discount = 0.8;
function getPrice(price) {
  return price * discount;
}

getPrice(100);
discount = 0.5;
getPrice(100);

上面的例子,每次调用getPrice函数传入的参数都是100但是因为要从外部获取discount的值会在外部变化,导致getPrice的值会变化,这个函数就不是纯函数

function getPrice(price, discount) {
  return price * discount;
}
getPrice(100, 0.8);

像这样所有的值,都由参数决定的,就是纯函数(没有副作用)

函数副作用

函数调用时会对主调用函数产生附加的影响,例如修改全局变量,会使代码维护变得困难。

compose函数

将需要嵌套执行的函数平铺,嵌套执行指的是,一个函数的返回值将作为另一个函数的参数。conpose函数主要是搜集函数,并且函数的执行是从右到左的。

实现一个数+10再*10的方式

复合函数实现

let add = x => x + 10;
let multiply = y => y * 10;
let compose = (f,g) => {
  return (x) => {
    return f(g(x));
  }
}

let result = compose(multiply, add);

可以复用的函数

let add = x => x + 10;
let multiply = y => y * 10;
 let compose = function() {
  // arguments 没有slice函数,但是[]有,这种方法可以给arguments绑定一个slice方法
 let args = [].slice.call(arguments);  
  return function(x) {
    return args.reduceRight((res, cb) => {
      return cb(res);
    }, x)
  }
} 

let result = compose(multiply, add);

arguments 可以得到函数传入的参数

es6 的写法

let add = x => x + 10;
let multiply = y => y * 10;
const compose = (...args) => (x) => {
  args.reduceRight((res, cb) => {
    cb(res)
  }, x)
}
let result = compose(multiply, add);

pipe函数

pipe函数执行从左向右

let add = x => x + 10;
let multiply = y => y * 10;
const pipe = (...args) => x => args.reduce((res, cb) => cb(res), x);
let result = pipe(add, multiply);
console.log('-------------result-------------------', result(10))