compose函數&pipe函數&柯里化函數&節流函數&防抖函數

compose函數 也就是複合函數 

const add = (x) => x + 10;

const multple = (y) => y * 10;

console.log(multple(add(10))); // 200

function compose() {
    const args = [].slice.call(arguments);
    return function(x) {
        if (!args.length) return x;
        if (args.length === 1) return args(x)
        // 從右往左執行 先支持add 再執行multple
        return args.reduceRight((res, fun) => fun(res), x)
    }
}

}

const cu = compose(multple, add);
console.log(cu(10)) // 200

pipe函數,管道函數

順序是從左往右,將reduceRight換成reduce就可以了。

const add = (x) => x + 10;

const multple = (y) => y * 10;

console.log(multple(add(10))); // 200

function compose() {
    const args = [].slice.call(arguments);
    return function(x) {
        if (!args.length) return x;
        if (args.length === 1) return args(x)
        // 從右往左執行 先支持add 再執行multple
        return args.reduce((res, fun) => fun(res), x)
    }
}

}

const cu = compose(multple, add);
console.log(cu(10)) // 200

柯里化函數  

柯里化就是將一個接收多個參數的函數轉化爲一系列使用一個參數的函數的技術。實現的效果就是

// 觀察上訴柯里化調用發現,它其實就是把參數都蒐集起來了,每次調用搜集幾個參數
// 當蒐集的參數足夠時執行主方法
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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章