Javascript高階函數(shù)

高階函數(shù)

概念

Javascript中的函數(shù)本質(zhì)上都指向某個(gè)變量,既然變量可以指向函數(shù)董朝,函數(shù)的參數(shù)可以接受變量找蜜,那么函數(shù)是不是可以可以作為另一個(gè)函數(shù)的入?yún)ⅲ恳驗(yàn)镴avascript是一門弱類型語(yǔ)言婚被,不會(huì)對(duì)函數(shù)輸入值和函數(shù)的輸出值進(jìn)行強(qiáng)定義和類型檢查狡忙。所以函數(shù)可以作為參數(shù),也可以作為輸出值址芯。

一個(gè)最簡(jiǎn)單的高階函數(shù):

let add=(x,y,f)=>f(x)+f(y);

對(duì)其他函數(shù)進(jìn)行操作的函數(shù)灾茁,可以將他們作為參數(shù)或返回它們窜觉。

高階函數(shù)分類

  • 函數(shù)作為參數(shù)傳遞
  • 函數(shù)作為返回值

map/reduce/filter

map

定義:map() 方法返回一個(gè)新數(shù)組,不會(huì)改變?cè)紨?shù)組北专。同時(shí)新數(shù)組中的元素為原始數(shù)組元素調(diào)用函數(shù)處理后的值禀挫,并按照原始數(shù)組元素順序依次處理元素。

語(yǔ)法:array.map(function(currentValue /*必填拓颓,當(dāng)前元素的值 */,index /*可選语婴,當(dāng)前元素的索引*/,arr /*可選,當(dāng)前元素屬于的數(shù)組對(duì)象*/), thisValue /*可選驶睦,上下文對(duì)象砰左,用作this,默認(rèn)為全局對(duì)象*/)

有以下需求:創(chuàng)建一個(gè)新數(shù)組场航,其中的值是原數(shù)組的值的兩倍缠导。

const arr=[1,2,3]
let fn=(arr)=>{
  let temp=[]
  for(let i=0;i<arr.length;i++){
    temp.push(arr[i]*2)
  }
  return temp;
}
console.log(fn(arr))

以上是我們的命令式編程,我們改寫下:

const temp=[1,2,3].map(item=>item*2)
console.log(temp)

在這里我們使用(item)=>item*2作為map函數(shù)的參數(shù)旗闽。

手動(dòng)實(shí)現(xiàn)map()酬核,遍歷函數(shù)的每一項(xiàng)作為函數(shù)的入?yún)ⅲ⒎祷孛看魏瘮?shù)調(diào)用結(jié)果組成的數(shù)組

關(guān)鍵:1.函數(shù)為空适室,返回空 2.func 必須是函數(shù)類型嫡意,需要有return值,否則會(huì)出現(xiàn)所有項(xiàng)映射為undefind 3.無(wú)副作用

Array.prototype.mapTest = function (func, content) {
  if (typeof func !== 'function') throw new TypeError(
    `${typeof func} is not a function`)
  let arrTemp = this.slice()
  content = typeof content === 'undefined' ? null : content
  let result = []
  for (let idx = 0; idx < arrTemp.length; idx++) {
    result.push(func.call(content, arrTemp[idx], idx, arrTemp))
  }
  return result
}

reduce

定義:reduce() 方法接收一個(gè)函數(shù)作為累加器捣辆,數(shù)組中的每個(gè)值(從左到右)開(kāi)始縮減蔬螟,最終計(jì)算為一個(gè)值

語(yǔ)法:array.reduce(function(total /*必需。初始值, 或者計(jì)算結(jié)束后的返回值*/, currentValue/*必需汽畴。當(dāng)前元素*/, currentIndex/*可選旧巾。當(dāng)前元素的索引*/, arr/*可選。當(dāng)前元素所屬的數(shù)組對(duì)象忍些。*/), initialValue/*可選鲁猩。傳遞給函數(shù)的初始值*/)

有以下需求:對(duì)數(shù)組arr的項(xiàng)進(jìn)行求和

let arr=[1,2,3,4]

// 命令式編程
let sum=arr=>{
  let temp=0;
  for(let idx=0;idx<arr.length;idx++){
    temp+=arr[idx]
  }
  return temp
}
//使用reduce
let total=arr.reduce((prev,cur)=>{
  return prev+cur
},0)

過(guò)程分析:

第一次執(zhí)行時(shí),prev的值為我們的初始值0罢坝,返回0+cur(當(dāng)前數(shù)組的第一位)作為第二次執(zhí)行時(shí)的prev….從而達(dá)到累加的目的廓握;

手動(dòng)實(shí)現(xiàn)一個(gè)reduce(),核心就是遍歷數(shù)組每一項(xiàng)參與函數(shù)運(yùn)算并將返回值作為下次遍歷的初始值嘁酿,從而實(shí)現(xiàn)累加隙券。

關(guān)鍵點(diǎn):1.無(wú)初始值時(shí),從原數(shù)組的第二項(xiàng)進(jìn)行遍歷 2.無(wú)副作用

Array.prototype.reduceTest = function(func, initVal, directionLeft = true) {
  if (typeof func !== 'function') throw new TypeError(`${typeof func} is not a function`)
  if (!this.length) {
    if (typeof initVal !== 'undefined') {
      return initVal
    } else {
      throw new Error('Reduce of empty array with no initial value')
    }
  }
  let array = this.slice()
  let hasInitVal = typeof initVal !== 'undefined'
  let value = hasInitVal ? initVal : array[0]
  if (directionLeft === false) {
    array = array.reverse()
  }
  for (let idx = hasInitVal ? 0 : 1; idx < array.length; idx++) {
    const cur = array[idx]
    value = func.call(null,value, cur, idx, array)
  }
  return value
}

filter

定義:filter() 方法創(chuàng)建一個(gè)新的數(shù)組闹司,新數(shù)組中的元素是通過(guò)檢查指定數(shù)組中符合條件的所有元素娱仔。

語(yǔ)法:array.filter(function(currentValue/*必須。當(dāng)前元素的值*/,index/*可選游桩。當(dāng)前元素的索引值*/,arr/*可選牲迫。當(dāng)前元素屬于的數(shù)組對(duì)象*/), thisValue/*可選耐朴。對(duì)象作為該執(zhí)行回調(diào)時(shí)使用,傳遞給函數(shù)盹憎,用作 "this" 的值*/)

需求:過(guò)濾出對(duì)象數(shù)組中age大于10的元素

let persons = [
  { 'name': 'Bob', age: 12 },
  { 'name': 'Lily', age: 13 },
  { 'name': 'Tom', age: 9 },
  { 'name': 'Jone', age: 99 },
]

// 命令式編程
let result=()=>{
  let res=[];
  for(let idx=0;idx<persons.length;idx++){
    if(persons[idx].age>10){
      res.push(persons[idx])
    }
  }
  return res;
}
// 使用filter
let filterResult=persons.filter(item=>item.age>9);

手動(dòng)實(shí)現(xiàn)一個(gè)filter()隔箍,核心就是創(chuàng)建一個(gè)新的數(shù)組,新數(shù)組中的元素是原數(shù)組中符合條件的項(xiàng)脚乡。

關(guān)鍵點(diǎn):1.函數(shù)返回值為true/false 2.無(wú)副作用

Array.prototype.filterTest=function (func,content) {
  if (typeof func !== 'function') throw new TypeError(`${typeof func} is not a function`)
  if (!this.length) return []
  let arr = this.slice()
  content = typeof content === 'undefined' ? null : content
  let result=[]
  for(let idx=0;idx<arr.length;idx++){
    let res=func.call(content,arr[idx],idx,arr)
    if(res){
      result.push(arr[idx])
    }
  }
  return result
}

flat

注意:普通瀏覽器(僅Chrome v69,F(xiàn)irefox Nightly和Opera 56等)/Node.js (需V11.0.0及以上) 尚未實(shí)現(xiàn)flat方法滨达。這是一項(xiàng)實(shí)驗(yàn)性功能奶稠。 [MDN 說(shuō)明以及替代方案]

用法:將目標(biāo)嵌套數(shù)組扁平化,變?yōu)樾碌囊痪S數(shù)組

語(yǔ)法:arrry.flat([depth]/*指定要提取嵌套數(shù)組的結(jié)構(gòu)深度捡遍,默認(rèn)值為 1锌订。Infinity為無(wú)限*/)

手動(dòng)實(shí)現(xiàn)一個(gè)flat()

/**
 * 數(shù)組扁平化
 * @param depth 拉平深度 默認(rèn)為1,最大為Infinity
 */
Array.prototype.flatTest = function (depth = 1) {
  let arr = this.slice()
  const result = []
  // 當(dāng)前已拉平層數(shù) 
  let flattenDepth = 1;
  // 先拉平第一層
  (function flatten (list) {
    list.forEach((item) => { 
      if (flattenDepth < depth &&Array.isArray(item)) {
        flattenDepth++
        flatten(item)
      } else {
        result.push(item)
      }
    })
  })(arr)
  return result
}

總結(jié)

高階函數(shù)本質(zhì)上就是對(duì)算法的高度抽象,通過(guò)提高抽象度画株,實(shí)現(xiàn)最大程度代碼重構(gòu)辆飘。

示例代碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市谓传,隨后出現(xiàn)的幾起案子蜈项,更是在濱河造成了極大的恐慌,老刑警劉巖续挟,帶你破解...
    沈念sama閱讀 207,248評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件紧卒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡诗祸,警方通過(guò)查閱死者的電腦和手機(jī)跑芳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)直颅,“玉大人博个,你說(shuō)我怎么就攤上這事」Τィ” “怎么了盆佣?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,443評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)脖含。 經(jīng)常有香客問(wèn)我罪塔,道長(zhǎng),這世上最難降的妖魔是什么养葵? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,475評(píng)論 1 279
  • 正文 為了忘掉前任征堪,我火速辦了婚禮,結(jié)果婚禮上关拒,老公的妹妹穿的比我還像新娘佃蚜。我一直安慰自己庸娱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布谐算。 她就那樣靜靜地躺著熟尉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪洲脂。 梳的紋絲不亂的頭發(fā)上斤儿,一...
    開(kāi)封第一講書(shū)人閱讀 49,185評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音恐锦,去河邊找鬼往果。 笑死,一個(gè)胖子當(dāng)著我的面吹牛一铅,可吹牛的內(nèi)容都是我干的陕贮。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼潘飘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼肮之!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起卜录,我...
    開(kāi)封第一講書(shū)人閱讀 37,112評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤戈擒,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后艰毒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體峦甩,經(jīng)...
    沈念sama閱讀 43,609評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評(píng)論 2 325
  • 正文 我和宋清朗相戀三年现喳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了凯傲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嗦篱,死狀恐怖冰单,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情灸促,我是刑警寧澤诫欠,帶...
    沈念sama閱讀 33,803評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站浴栽,受9級(jí)特大地震影響荒叼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜典鸡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評(píng)論 3 307
  • 文/蒙蒙 一被廓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧萝玷,春花似錦嫁乘、人聲如沸昆婿。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,357評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)埠巨。三九已至团甲,卻和暖如春矗晃,著一層夾襖步出監(jiān)牢的瞬間枫吧,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,590評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工直奋, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留狼荞,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評(píng)論 2 355
  • 正文 我出身青樓帮碰,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親拾积。 傳聞我的和親對(duì)象是個(gè)殘疾皇子殉挽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 本期開(kāi)始介紹 JavaScript 中的高階函數(shù),在 JavaScript 中拓巧,函數(shù)是一種特殊類型的對(duì)象斯碌,它們是 ...
    編程小世界閱讀 482評(píng)論 0 0
  • 高階函數(shù) 在 JavaScript 中,函數(shù)是一種特殊類型的對(duì)象肛度,它們是 Function objects傻唾。高階函...
    PalSylo閱讀 342評(píng)論 1 9
  • 學(xué)習(xí)筆記,非原創(chuàng)承耿。謝謝 高階函數(shù) 高階函數(shù)英文叫Higher-order function冠骄。那么什么是高階函數(shù)? ...
    Rising_life閱讀 438評(píng)論 0 8
  • 概念 所謂的高階函數(shù)就是: 函數(shù)可以作為參數(shù) 函數(shù)可以作為返回值 filter 上面的代碼很簡(jiǎn)單加袋,上面代碼只是為了...
    無(wú)跡落花閱讀 549評(píng)論 0 3
  • 一凛辣、數(shù)組 1.concat( )用途:合并數(shù)組;不改變現(xiàn)有數(shù)組职烧,返回新數(shù)組扁誓;參考:MDN array.concat...
    Summer_zxm閱讀 474評(píng)論 0 1