柯里化(currying)與部分應(yīng)用(partial application) / 優(yōu)化嵌套的條件語句 / 運(yùn)用存儲(chǔ)加速遞歸

JavaScript的那些奇技淫巧

馬躍Marico4 天前

一. No1.柯里化(currying)與部分應(yīng)用(partial application)
柯里化(currying)
柯里化是使一個(gè)函數(shù)
f: X * Y -> R
轉(zhuǎn)變?yōu)?br> f’: X -> (Y -> R)
與用兩個(gè)參數(shù)調(diào)用f不同,我們用一個(gè)參數(shù)運(yùn)行f’。返回的結(jié)果是一個(gè)函數(shù)褂乍,然后用第二個(gè)參數(shù)調(diào)用此函數(shù)轰豆,得到結(jié)果寡润。
如此赴邻,如果未柯里化的函數(shù)f這樣調(diào)用
f(3,5)
柯里化后的函數(shù)f’是這樣調(diào)用的
f(3)(5)
比如: 未柯里化的函數(shù)add()
function add(x, y) { return x + y;}add(3, 5); // returns 8

柯里化后的add()
function addC(x) { return function (y) { return x + y; }}addC(3)(5); // returns 8

柯里化的規(guī)則
柯里化將一個(gè)二元函數(shù)书闸,轉(zhuǎn)變?yōu)橐辉瘮?shù)审胸,這個(gè)函數(shù)將返回另一個(gè)一元函數(shù)亥宿。
curry: (X × Y → R) → (X → (Y → R))
Javascript Code:
function curry(f) { return function(x) { return function(y) { return f(x, y); } }}

部分應(yīng)用(partial application)
部分應(yīng)用將一個(gè)函數(shù)
f: X * Y -> R
的第一個(gè)參數(shù)固定而產(chǎn)生一個(gè)新的函數(shù)
f`: Y -> R
f’與f不同,只需要填寫第二個(gè)參數(shù)砂沛,這也是f’比f少一個(gè)參數(shù)的原因烫扼。
比如:將函數(shù)add的第一個(gè)參數(shù)綁定為5來產(chǎn)生函數(shù)plus5。
function plus5(y) { return 5 + y;}plus5(3); // returns 8

部分應(yīng)用的規(guī)則
部分應(yīng)用使用一個(gè)二元函數(shù)和一個(gè)值產(chǎn)生了一個(gè)一元函數(shù)碍庵。
partApply : ((X × Y → R) × X) → (Y → R)
Javascript Code:
function partApply(f, x) { return function(y) { return f(x, y); }}

No2.優(yōu)化嵌套的條件語句
我們?cè)鯓觼硖岣吆蛢?yōu)化javascript里嵌套的if語句呢映企?
if (color) { if (color === 'black') { printBlackBackground(); } else if (color === 'red') { printRedBackground(); } else if (color === 'blue') { printBlueBackground(); } else if (color === 'green') { printGreenBackground(); } else { printYellowBackground(); }}

一種方法來提高嵌套的if語句是用switch語句。雖然它不那么啰嗦而且排列整齊静浴,但是并不建議使用它堰氓,因?yàn)檫@對(duì)于調(diào)試錯(cuò)誤很困難。這告訴你為什么苹享。
switch(color) { case 'black': printBlackBackground(); break; case 'red': printRedBackground(); break; case 'blue': printBlueBackground(); break; case 'green': printGreenBackground(); break; default: printYellowBackground();}

如果可以重構(gòu)的話双絮,我們可以試著簡(jiǎn)化函數(shù)。比如不需要為每個(gè)顏色寫一個(gè)函數(shù)得问,而是將顏色作為函數(shù)的參數(shù)囤攀。
function printBackground(color) { if (!color || typeof color !== 'string') { return; }}

但是如果不能重構(gòu)的話,我們必須避免過多的條件檢查宫纬,避免過多使用switch抚岗。我們必須考慮最有效率的方法,使用object哪怔。
let colorObj = { 'black': printBlackBackground, 'red': printRedBackground, 'blue': printBlueBackground, 'green': printGreenBackground, 'yellow': printYellowBackground};if (color in colorObj) { colorObjcolor;}

No3.運(yùn)用存儲(chǔ)加速遞歸
大家對(duì)斐波那契(Fibonacci)數(shù)列都很熟悉宣蔚。我們可以再20秒內(nèi)寫出下面這樣一個(gè)方法向抢。
var fibonacci = function(n){ return n < 2 ? n : fibonacci(n-1) + fibonacci(n-2);}

它可以運(yùn)行,但并不高效胚委。它做了太多重復(fù)的運(yùn)算挟鸠,我們可以通過存儲(chǔ)這些運(yùn)算結(jié)果來使其加速。
var fibonacci = (function() { var cache = [0, 1]; // cache the value at the n index return function(n) { if (cache[n] === undefined) { for (var i = cache.length; i <= n; ++i) { cache[i] = cache[i-1] + cache[i-2]; } } return cache[n]; }})()

我們也可以定義一個(gè)高階函數(shù)亩冬,它接收一個(gè)方法作為參數(shù)艘希,返回一個(gè)該方法運(yùn)用存儲(chǔ)后的新方法。
var memoize = function(func){ var cache = {}; return function(){ var key = Array.prototype.slice.call(arguments).toString(); return key in cache ? cache[key] : (cache[key] = func.apply(this,arguments)); }}fibonacci = memoize(fibonacci);

ES6版本的memoize函數(shù)如下:
var memoize = function(func){ const cache = {}; return (...args) => { const key = [...args].toString(); return key in cache ? cache[key] : (cache[key] = func(...args)); }}fibonacci = memoize(fibonacci);

我們可以將memoize()用在很多其他地方

  • GCD(最大公約數(shù))
    var gcd = memoize(function(a,b){ var t; if (a < b) t=b, b=a, a=t; while(b != 0) t=b, b = a%b, a=t; return a;})gcd(27,183); //=> 3

  • 階乘運(yùn)算
    var factorial = memoize(function(n) { return (n <= 1) ? 1 : n * factorial(n-1);})factorial(5); //=> 120

Original:[Js Tips - A JavaScript tip per day!*
") 0px 2px / cover;">*
](Js Tips - A JavaScript tip per day!*
") 0px 2px / cover;">*
)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末硅急,一起剝皮案震驚了整個(gè)濱河市覆享,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌营袜,老刑警劉巖撒顿,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異荚板,居然都是意外死亡凤壁,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門跪另,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拧抖,“玉大人,你說我怎么就攤上這事免绿∵笙” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵嘲驾,是天一觀的道長(zhǎng)淌哟。 經(jīng)常有香客問我,道長(zhǎng)距淫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任婶希,我火速辦了婚禮榕暇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘喻杈。我一直安慰自己彤枢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布筒饰。 她就那樣靜靜地躺著缴啡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪瓷们。 梳的紋絲不亂的頭發(fā)上业栅,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天秒咐,我揣著相機(jī)與錄音,去河邊找鬼碘裕。 笑死携取,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的帮孔。 我是一名探鬼主播雷滋,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼文兢!你這毒婦竟也來了晤斩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤姆坚,失蹤者是張志新(化名)和其女友劉穎澳泵,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旷偿,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烹俗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了萍程。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片幢妄。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖茫负,靈堂內(nèi)的尸體忽然破棺而出蕉鸳,到底是詐尸還是另有隱情,我是刑警寧澤忍法,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布潮尝,位于F島的核電站,受9級(jí)特大地震影響饿序,放射性物質(zhì)發(fā)生泄漏勉失。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一原探、第九天 我趴在偏房一處隱蔽的房頂上張望乱凿。 院中可真熱鬧,春花似錦咽弦、人聲如沸徒蟆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽段审。三九已至,卻和暖如春闹蒜,著一層夾襖步出監(jiān)牢的瞬間寺枉,已是汗流浹背抑淫。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留型凳,地道東北人丈冬。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像甘畅,于是被迫代替她去往敵國和親埂蕊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

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

  • 1.函數(shù)參數(shù)的默認(rèn)值 (1).基本用法 在ES6之前疏唾,不能直接為函數(shù)的參數(shù)指定默認(rèn)值蓄氧,只能采用變通的方法。
    趙然228閱讀 688評(píng)論 0 0
  • 原文鏈接 Haskell和scala都支持函數(shù)的柯里化,JavaScript函數(shù)的柯里化還與JavaScript的...
    dreamapple閱讀 2,525評(píng)論 0 24
  • SwiftDay011.MySwiftimport UIKitprintln("Hello Swift!")var...
    smile麗語閱讀 3,834評(píng)論 0 6
  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗(yàn)槐脏。 張土汪:刷leetcod...
    土汪閱讀 12,744評(píng)論 0 33
  • 今天顿天,是不平靜的一天堂氯,沒有遇到意外,也沒有身體不舒服牌废,是內(nèi)心好久以來沒有這樣像過電影一樣回想起往日的種種場(chǎng)景咽白,...
    佳貝健康閱讀 141評(píng)論 0 1