摘要:忍者秘籍一書中,對于柯里化的定義如下在一個(gè)函數(shù)中首先填充幾個(gè)參數(shù)然后再返回一個(gè)新函數(shù)的技術(shù)稱為柯里化。回到我們的題目本身,其實(shí)根據(jù)測試用例我們可以發(fā)現(xiàn),函數(shù)的要求就是接受單一函數(shù),例如但是與柯里化不同之處在于,柯里化返回的一個(gè)新函數(shù)。
歡迎大家再一次來到我的文章專欄:從面試題中我們能學(xué)到什么,各位同行小伙伴是否已經(jīng)開始了悠閑的春節(jié)假期呢?在這里提前祝大家雞年大吉吧~哈哈,之前有人說,學(xué)面試題不會有什么長進(jìn),其實(shí)我覺得這個(gè)就像是我們英語考試中的閱讀理解,帶著問題去看文章反而更有利于自己的學(xué)習(xí)。
之前的兩篇文章:
一道頗有難度的JavaScript題
一個(gè)小小的JavaScript題目
都在稀土掘金和Segmentfault都獲得了非常多的點(diǎn)擊量,沒有看的小伙伴們可以點(diǎn)擊了解一下,今天為大家?guī)硪坏狸P(guān)于閉包和函數(shù)的柯里化方面的編程題目,各位小伙伴有沒有開始躍躍欲試呢?
編程題目的要求如下,完成plus函數(shù),通過全部的測試用例。
"use strict"; function plus(n){ } module.exports = plus
測試用例如下
"use strict"; var assert = require("assert") var plus = require("../lib/assign-4") describe("閉包應(yīng)用",function(){ it("plus(0) === 0",function(){ assert.equal(0,plus(0).toString()) }) it("plus(1)(1)(2)(3)(5) === 12",function(){ assert.equal(12,plus(1)(1)(2)(3)(5).toString()) }) it("plus(1)(4)(2)(3) === 10",function(){ assert.equal(10,plus(1)(4)(2)(3).toString()) }) it("方法引用",function(){ var plus2 = plus(1)(1) assert.equal(12,plus2(1)(4)(2)(3).toString()) }) })
實(shí)話說剛開始拿到這道題的時(shí)候我并沒有完全的做出來,但是具體的思路是有的,肯定是關(guān)于函數(shù)的柯里化(Currying)方面的,應(yīng)該是想考察一下面試者的閉包理解能力.
那么首先介紹一下什么是函數(shù)的柯里化(Currying)。《JavaScript忍者秘籍》一書中,對于柯里化的定義如下:
在一個(gè)函數(shù)中首先填充幾個(gè)參數(shù)(然后再返回一個(gè)新函數(shù))的技術(shù)稱為柯里化(Currying。
維基百科中關(guān)于其定義如下:
在計(jì)算機(jī)科學(xué)中,柯里化(Currying),又譯為卡瑞化或加里化,是把接受多個(gè)參數(shù)的函數(shù)變換成接受一個(gè)單一參數(shù)(最初函數(shù)的第一個(gè)參數(shù))的函數(shù),并且返回接受余下的參數(shù)而且返回結(jié)果的新函數(shù)的技術(shù)。這個(gè)技術(shù)由克里斯托弗·斯特雷奇以邏輯學(xué)家哈斯凱爾·加里命名的。
首先我們舉個(gè)例子來具體的解釋一下以上的概念。
例如一個(gè)最簡單的加法函數(shù):
//函數(shù)定義 function add(x,y){ return x + y; } //函數(shù)調(diào)用 add(3,4);//5
如果采用柯里化是怎樣將接受兩個(gè)參數(shù)的函數(shù)變成接受單一參數(shù)的函數(shù)呢,其實(shí)很簡單如下:
//函數(shù)表達(dá)式定義 var add = function(x){ return function(y){ return x + y; } }; //函數(shù)調(diào)用 add(3)(4);
這樣理解起來其實(shí)是不是就很簡單了,其實(shí)實(shí)質(zhì)利用的就是閉包的概念(大家可以在我的另一篇文章淺談JavaScript閉包看一下)。本質(zhì)上講柯里化(Currying)只是一個(gè)理論模型,柯里化所要表達(dá)是:如果你固定某些參數(shù),你將得到接受余下參數(shù)的一個(gè)函數(shù),所以對于有兩個(gè)變量的函數(shù)y^x,如果固定了y=2,則得到有一個(gè)變量的函數(shù)2^x。這就是求值策略中的部分求值策略。
柯里化(Currying)具有:延遲計(jì)算、參數(shù)復(fù)用、動(dòng)態(tài)生成函數(shù)的作用。例如如果我們需要?jiǎng)?chuàng)建一個(gè)通用的DOM事件綁定函數(shù),不使用柯里化的寫法如下(該示例來自于博客園Tong Zeng):
//第四個(gè)參數(shù)用來標(biāo)識是在冒泡階段還是在捕獲階段執(zhí)行函數(shù) var addEvent = function(el,type,fn,capture){ if (window.addEventListener) { el.addEventListener(type, function(e) { fn.call(el, e); }, capture); } else if (window.attachEvent) { el.attachEvent("on" + type, function(e) { fn.call(el, e); }); } }
但是在使用了柯里化(Currying)的情況下,不再需要每次添加事件處理都要執(zhí)行一遍if...else...判斷,只需要在瀏覽器中判定一次就可以了,把根據(jù)一次判定之后的結(jié)果動(dòng)態(tài)生成新的函數(shù),以后就不必重新計(jì)算。其實(shí)在實(shí)際使用中使用最多的一個(gè)柯里化的例子就是Function.prototype.bind()函數(shù),我們也一并給出一個(gè)較為簡單的Function.prototype.bind()函數(shù)的實(shí)現(xiàn)方式。
Function.prototype.bind = function(){ var fn = this; var args = Array.prototye.slice.call(arguments); var context = args.shift(); return function(){ return fn.apply(context, args.concat(Array.prototype.slice.call(arguments))); }; };
回到我們的題目本身,其實(shí)根據(jù)測試用例我們可以發(fā)現(xiàn),plus函數(shù)的要求就是接受單一函數(shù),例如:
plus(1)(4)(2)(3).toString()
但是與柯里化不同之處在于,柯里化返回的一個(gè)新函數(shù)。我們觀察其實(shí)最后的求值是通過toString函數(shù)得到的,那么我們就很容易想到,我們可以給返回的函數(shù)增加一個(gè)toString屬性就可以了。我自己寫出的答案如下:
/** * Created by lei.wang on 2017/1/22. */ "use strict"; function plus(num) { var adder = function () { var _args = []; var _adder = function _adder() { [].push.apply(_args, [].slice.call(arguments)); return _adder; }; _adder.toString = function () { return _args.reduce(function (a, b) { return a + b; }); } return _adder; } return adder()(num); } module.exports = plus;
運(yùn)行一下,通過全部的測試用例,需要注意的是由于題目的要求運(yùn)行在嚴(yán)格模式下,所以我們在_adder函數(shù)內(nèi)部是不能引用arguments.callee,這時(shí)我們采用的方法是給函數(shù)表達(dá)式中函數(shù)本身起名_adder,這樣就解決的這個(gè)問題。
再次感謝大家閱讀本篇文章,希望大家能從中或多或少學(xué)到一些東西,入行資歷甚淺,不足之處請多指教,歡迎大家在去我的博客MrErHu中留言打賞,愿大家一同進(jìn)步。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/81316.html
摘要:對于函數(shù)的柯里化應(yīng)該不陌生,簡單來說技術(shù)是一種通過把多個(gè)參數(shù)填充到函數(shù)體中,實(shí)現(xiàn)將函數(shù)轉(zhuǎn)換為一個(gè)新的經(jīng)過簡化的使之接受的參數(shù)更少函數(shù)的技術(shù)。 對于函數(shù)的柯里化(currying)應(yīng)該不陌生,簡單來說 Currying 技術(shù)是一種通過把多個(gè)參數(shù)填充到函數(shù)體中,實(shí)現(xiàn)將函數(shù)轉(zhuǎn)換為一個(gè)新的經(jīng)過簡化的(使之接受的參數(shù)更少)函數(shù)的技術(shù)。當(dāng)發(fā)現(xiàn)正在調(diào)用同一個(gè)函數(shù)時(shí),并且傳遞的參數(shù)絕大多數(shù)都是相同的,...
摘要:如果你對函數(shù)式編程有一定了解,函數(shù)柯里化是不可或缺的,利用函數(shù)柯里化,可以在開發(fā)中非常優(yōu)雅的處理復(fù)雜邏輯。同樣先看簡單版本的方法,以方法為例,代碼來自高級程序設(shè)計(jì)加強(qiáng)版實(shí)現(xiàn)上面函數(shù),可以換成任何其他函數(shù),經(jīng)過函數(shù)處理,都可以轉(zhuǎn)成柯里化函數(shù)。 我們經(jīng)常說在Javascript語言中,函數(shù)是一等公民,它們本質(zhì)上是十分簡單和過程化的。可以利用函數(shù),進(jìn)行一些簡單的數(shù)據(jù)處理,return 結(jié)果,...
摘要:碰到這種面試官,你只有是個(gè)題霸,再加上眼緣夠才能順利入圍。只要按照我題目的思路,甚至打出來測試用例看看,就能實(shí)現(xiàn)這個(gè)題目了。答案根據(jù)的,對答案做出修正。另我的答案絕不敢稱最佳,隨時(shí)歡迎優(yōu)化修正。但了解總歸是好的。 我們在長期的面試過程中,經(jīng)歷了種種苦不堪言,不訴苦感覺不過癮(我盡量控制),然后主要聊聊常見JavaScript面試題的解法,以及面試注意事項(xiàng) 憶苦 面試第一苦,面試官的土 ...
摘要:接下來的函數(shù)就有點(diǎn)難度了,讓我們一行一行來看。上面實(shí)際的含義就是將數(shù)組每一個(gè)執(zhí)行的返回值保存的數(shù)組中。需要注意的是,方法返回值并不是數(shù)組,而是形如初始值的經(jīng)過疊加處理后的操作。從而實(shí)現(xiàn)異步的。 這段時(shí)間都在學(xué)習(xí)Redux,感覺對我來說初學(xué)難度很大,中文官方文檔讀了好多遍才大概有點(diǎn)入門的感覺,小小地總結(jié)一下,首先可以看一下Redux的基本流程:showImg(https://segm...
摘要:面試題實(shí)現(xiàn)結(jié)果,題的核心就是問的的柯里化先說說什么是柯里化,看過許多關(guān)于柯里化的文章,始終搞不太清楚,例如柯里化是把接受多個(gè)參數(shù)的函數(shù)變換成接受一個(gè)單一參數(shù)最初函數(shù)的第一個(gè)參數(shù)的函數(shù),并且返回接受余下的參數(shù)且返回結(jié)果的新函數(shù)的技術(shù)。 面試題:實(shí)現(xiàn)add(1)(2)(3) //結(jié)果 = 6,題的核心就是問的js的柯里化 先說說什么是柯里化,看過許多關(guān)于柯里化的文章,始終搞不太清楚,例如...
閱讀 2543·2023-04-26 00:56
閱讀 2000·2021-10-25 09:46
閱讀 1236·2019-10-29 15:13
閱讀 811·2019-08-30 15:54
閱讀 2190·2019-08-29 17:10
閱讀 2611·2019-08-29 15:43
閱讀 497·2019-08-29 15:28
閱讀 3022·2019-08-29 13:24