【JS】柯理化函数 数组reduce方法 箭头函数 compose函数思想

1,032 阅读4分钟

柯理化函数思想

柯理化函数思想利用的是闭包的机制,把一些信息预先存储下来,是一种预处理的思想。

function fn(...arg1){
  return function anonymous(...arg2){
    let args = arg1.concat(arg2);
    return args.reduce((n,item) =>n+item);
  }
}
let res =fn(1,2)(3);
console.log(res);

//=> 6

数组reduce方法

reduce方法有两个参数:

  • 回调函数,回调函数里面有两个参数:
    • pre:上一项
    • next:下一项
  • 第二个参数可以修改第一次的pre

上一次回调函数的return的值作为下一次的回调函数的n,而下一次的item是数组的下一项


下面是两种传参的情况

  • 没有传第二个参数的情况:只传了第一个参数,是一个回调函数
let ary =[10,20,30,40,50,60];
let res =ary.reduce((n,item)=>{

console.log(n,item);
return n+item;

});
console.log(res);

//=>10 20
    30 30
    60 40
    100 50
    150 60
    210

解析: 第一次触发回调函数执行的n是数组第一项,item是数组第二项;第二次执行时,n是第一次执行的return的值,本代码中是数组第一项加数组第二项的结果,而item则是数组的第三项;第x次执行时,n是第x-1次回调函数的返回结果,item是数组的第x+1项。

  • 传第二个参数的情况:如果传了第二个参数,则第一次执行时,n是第二个参数,而item是数组的第一项
let ary =[10,20,30,40,50,60];
let res =ary.reduce((n,item)=>{

console.log(n,item);
return n+item;

},0);
console.log(res);

//=> 0 10
     10 20
     30 30
     60 40
     100 50
     150 60
     210

箭头函数

箭头函数的特点

首先,箭头函数省略了function关键词

let res = function(x,y){}

let res = (x,y) => {}

另外,如果只有一个形参,则可以把小括号省略

let res = x =>{}

还有,如果大括号里面只有 return 一个值,大括号也可以省略了

let res = function (x,y){
return x+y;
}

let res = (x,y) => x+y ;

如果只有一个参数,还只有return一个值的话,就非常的方便了

let res = x => ++x;

console.log(res(1));

//=> 2

注意: 不过箭头函数中没有this,它里面的this是上级作用域中的this

箭头函数的this指向问题

箭头函数本身不创建this;

也可以说箭头函数本身没有this,但是在它声明时可以捕获别人的this供自己使用。

特别说明: this一旦被捕获,以后将不再变化。

箭头函数中的this是在它声明时捕获它所处作用域中的this。

即使用 call、apply或bind 也无法改变箭头函数this的指向

箭头函数与普通函数的区别

  • 外形不同:箭头函数使用箭头定义,普通函数中没有。
  • 箭头函数全都是匿名函数:普通函数可以有匿名函数,也可以有具名函数。
  • 箭头函数不能用于构造函数:普通函数可以用于构造函数,以此创建对象实例。
  • 箭头函数中this的指向不同。这一点在上文和我的其他博客中都有专门的说明,此处不做赘述
  • 箭头函数不具有arguments对象:每一个普通函数调用后都具有一个arguments对象,用来存储实际传递的参数。但是箭头函数并没有此对象。
  • 其他区别:

(1).箭头函数不能Generator函数。

(2).箭头函数不具有prototype原型对象。

(3).箭头函数不具有super。

(4).箭头函数不具有new.target。

compose思想

compose:组合函数,把嵌套调用的多层函数实现扁平化

const fn1 = x => x+10;
const fn2 = x => x-10;
const fn3 = x => x*10;
const fn4 = x => x/10;

let res = fn4(fn3(fn2(fn1(20))));
console.log(res);

使用 compose 思想,手写一个compose函数,实现上述的函数调用,并且让函数执行顺序更加清晰,便于理解

const fn1 = x => x+10;
const fn2 = x => x-10;
const fn3 = x => x*10;
const fn4 = x => x/10;

function compose(...arg1){
//arg1中存储按顺序执行的函数(数组) => [fn1,fn2,fn3,fn4]
   return function(...arg2){
   //arg2存储第一个函数执行需要传递的实参信息(数组) =>[20]
   //判断传进来的函数构成的数组arg1的长度
   if(arg1.length === 0){return arg2};
   if(arg1.length === 1){return arg1[0](...arg2)};
  return arg1.reduce(function(pre,next){
   // 第一次的pre的值:第一个函数执行的实参,next是第一个函数
   //第二次的pre的值:上一次next执行的返回值,作为实参传递给下一个函数执行
   return Array.isArray(pre)?next(...pre):next(pre);
   },arg2);
   };
}

let res = compose(fn1,fn2,fn3,fn4)(20);
console.log(res);

//=> 20

这样一来,执行compose函数时,传参的顺序就是函数执行的顺序。