compose函数&pipe函数&柯里化函数&节流函数&防抖函数

compose函数 也就是复合函数 

简单的实现:

function add(x) {
        return x + 1
    }
    function multiply(x) {
        return x * 10
    }
    // 接收两个参数,先执行右边的函数
    function compose(a, b) {
        return function(x) {
            return a(b(x))
        }
    }
    const calculate = compose(add, multiply)
    console.log(calculate(2)) // 21

更通用的实现: 

function add(x) {
        return x + 1
    }
    function multiply(x) {
        return x * 10
    }
    // 接收两个参数,先执行右边的函数
    function compose() {
        const args = Array.prototype.slice.call(arguments)
        return function(x) {
            if(args.length < 1) return x
            return args.reduceRight((a, b) =>  b(a), x)
        }
    }
    const calculate = compose(add, multiply)
    console.log(calculate(2)) // 21

pipe函数,管道函数

顺序是从左往右,将reduceRight换成reduce就可以了。

function add(x) {
        return x + 1
    }
    function multiply(x) {
        return x * 10
    }
    // 接收两个参数,先执行右边的函数
    function pipe() {
        const args = Array.prototype.slice.call(arguments)
        return function(x) {
            if(args.length < 1) return x
            return args.reduce((a, b) =>  b(a), x)
        }
    }
    const calculate = compose(add, multiply)
    console.log(calculate(2)) // 21

柯里化函数  

柯里化就是将一个接收多个参数的函数转化为一系列使用一个参数的函数的技术。也就是将一个n元函数,转化为n个一元函数。

偏函数是固定一个参数的一个或者多个函数,也就是将一个n元函数,转化n-x个一元函数。

实现的效果就是

// 观察上诉柯里化调用发现,它其实就是把参数都搜集起来了,每次调用搜集几个参数
// 当搜集的参数足够时执行主方法
const curry = (fn) => {
  // 先记录主方法原始的参数个数,fn.length就是函数接收的参数个数
  const parmasLength = fn.length;

  return executeFun = (...args) => {
    // 如果接收参数够了,执行主方法
    if(args.length >= parmasLength) {
      return fn(...args);
    } else {
      // 如果参数不够,继续接收参数
      return (...args2) => {
        // 注意executeFun接收的参数是平铺的,需要将数组解构
        return executeFun(...args.concat(args2));
      }
    }
  }
}

const curriedFun = curry((a, b, c) => [a, b, c])
// 现在看下结果

console.log(curriedFun(1)(2)(3)) // [1, 2, 3]
console.log(curriedFun(1, 2)(3)) // [1, 2, 3]
console.log(curriedFun(1, 2, 3)) // [1, 2, 3]

fun.length是函数接受的形参的个数,arguments.length是函数接受的实参的个数。

function curry() {
    console.log(1)
}

console.log(curry.length) // 0

function curry1(a) {
    console.log(1)
}
console.log(curry1.length) // 1

function curry2(a) {
    console.log(arguments.length) // 0
}
console.log(curry2.length) // 1
curry2()

注意,如果以es6剩余参数的方式,fun.length不包含剩余参数。

function curry3(a, b, ...reset) {
    console.log(arguments.length) // 5
    console.log(reset) // [ 3, 4, 8]
}
console.log(curry3.length) // 2
curry3(1, 2, 3, 4, 8)

函数防抖 debounce
原理:将若干函数调用合成为一次,并在给定时间过去之后,或者连续事件完全触发完成之后,调用一次(仅仅只会调用一次)

可以去看下阿里巴巴的搜索框,当我们一直输入的时候,不去请求,当我们输入停止的时候,立马去发送请求。这里用到了防抖。

  /* 
   * 防抖函数
   * @param {Function} fun 要执行的函数
   *
   * @param {number} delay 一般是毫秒 时间周期,两个函数触发的时间间隔在时间周期内,不执行 否则,执行
  */
 
debounce(fun, delay) {
    let timer
    return function(...args) {
      if(timer) {
        clearTimeout(timer)
      }
      // 只有滚动事件停止前最后一次触发的timer才会执行
      timer = setTimeout(()=>{
        fun.apply(this, args)
      },delay)
    }
  }
document.addEventListener('scroll', debounce(function(){
  console.log(0)
}, 1000))


函数节流 throttle
原理:当达到了一定的时间间隔就会执行一次;可以理解为是缩减执行频率

 

看下网易严选的搜索框,当我们一直在输入的时候,是每隔一段时间请求一次。这里用到的是节流。

 /**
   * 节流函数 一段时间执行一次
   * 
   * @param {Function} fun 
   * @param {number} delay 
   */
  throttle(fun, delay) {
    let previous = 0;
    return function(...args) {
      const now = +new Date();
      if(now - previous > delay) {
        fun.apply(this, args)
        previous = now
      }
      
    }
  }

数组的扁平化

const flat = (arr, depth, initVal) => {
  const startVal = initVal || [];
  return arr.reduce((prevRes, item) => {
    // 如果里层还是数组,递归调用自身
    if(Array.isArray(item) && depth > 1){
      return flat(item, depth - 1, prevRes);
    }else{
      return prevRes.concat(item);
    }
  }, startVal)
}

const arr = [1, 2, [3, 4], [5, 6, [7, 8]]];
const flatArr = flat(arr, 1); // 只扁平化一层

console.log(flatArr);

 

http://www.dennisgo.cn/Articles/JavaScript/MemoryManagement.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值