摘要:最直接的方式當(dāng)然是遍歷數(shù)組并累加得到結(jié)果,也可以使用數(shù)組的方法實現(xiàn),如下結(jié)合第四步,替換中的返回值即可將其進(jìn)行簡化,得到最終結(jié)果當(dāng)然,采用這種實現(xiàn)方式,對于形如的調(diào)用方式也是沒有問題的。
第一步:實現(xiàn)級聯(lián)談?wù)?JavaScript 中形如 add(1)(2)(3)(4) = 10 這種累加器方法的實現(xiàn)過程和思路
若是想要實現(xiàn) fn()() 這種調(diào)用方式的函數(shù),則在 fn 函數(shù)體內(nèi)一定也會返回一個函數(shù),如下:
function fn(){ return function(){ } }
再進(jìn)一步,若是想要實現(xiàn) fn()()()... 不定次數(shù)的調(diào)用,則意味著每一層的返回值均為一個函數(shù),這就需要使用類似遞歸的方式去實現(xiàn):
function fn(){ var _fn = function(){ return _fn; } return _fn; }第二步:實現(xiàn)返回值
如果每一層的返回值均為函數(shù),那么如何返回累加結(jié)果呢?也就是說,在函數(shù)調(diào)用的最后一層,這個返回值應(yīng)該是一個值而非函數(shù)。這里則需要使用 valueOf 這一方法,例子如下:
function fn1(){ } console.log(fn1); // function ... function fn2(){ } fn2.valueOf = function(){ return 1; } console.log(fn2); // function 1
注意,fn2 在控制臺的輸出結(jié)果為 function 1,但其數(shù)值型隱式轉(zhuǎn)換的結(jié)果為 1,也就是說 console.log(+fn2) 或是 var num = fn2 + 1 是可以正常地作為數(shù)值型進(jìn)行計算的。而 fn2() 的方式仍然可以將其作為函數(shù)運算。
因而,我們只要給 _fn 添加 valueOf 方法就可以實現(xiàn)在不定次調(diào)用之后,得到一個「值」而非「函數(shù)」,如下:
function fn(){ var _fn = function(){ return _fn; } _fn.valueOf = function(){ return 12345; } return _fn; }
第三步:獲得傳入的參數(shù)這里也可以使用添加 toString() 的方式實現(xiàn)這一功能,與 valueOf() 做法一致。
這一步相對簡單,使用內(nèi)置對象 arguments 即可實現(xiàn)對函數(shù)中所傳入的參數(shù)的獲取,如下:
function foo(){ console.log(arguments); } foo(1,2,3);
注意,這里的 arguments 不是數(shù)組,而是對象:
{ 0 : 1, 1 : 2, 2 : 3, callee : function foo(), length : 3, Symbol(Symbol.iterator) : function values(), __proto__ : Object, }
若要將其轉(zhuǎn)換為數(shù)組,可以使用如下方式:
var arr = [].slice.call(arguments); // 或是 var arr = Array.prototype.slice.call(arguments);
第四步:實現(xiàn)參數(shù)保存若一個對象含有 length 屬性,則可以通過這種方式轉(zhuǎn)換為數(shù)組形式
add(1)(2)(3)... 累加器是在最后一次調(diào)用后返回之前所有參數(shù)的累加和。也就是說我們需要有一個地方可以保存先前的值或是計算結(jié)果。
在之前的代碼框架下,顯然不能將其保存在內(nèi)層的 _fn 中。因為每層調(diào)用都相當(dāng)于又一次的 _fn() 執(zhí)行,在其中定義的變量會被覆蓋。
使用全局變量當(dāng)然是一種方式,但是這樣會污染全局空間,不是最佳方案。
考慮到對 fn()()()... 的調(diào)用實際返回的是內(nèi)層的 _fn,意味著 fn 的局部變量其實也相當(dāng)于 _fn 的全局變量。因而可以將保存先前參數(shù)的職責(zé)交給 fn 中的一個變量,代碼如下:
function fn(){ var numList = []; var _fn = function(){ // 這里測試思路是否可行 numList.push(1); console.log(numList); return _fn; } _fn.valueOf = function(){ return 12345; } return _fn; } console.log(fn()()()); // [1, 1] // 注意這里雖然調(diào)用三次,但實際只執(zhí)行了兩次 push(1),第一次調(diào)用沒有執(zhí)行內(nèi)層的 _fn(),而只是返回了它。
結(jié)合第三步,我們可以通過 push() 或是 concat() 的方式將每一次的參數(shù)組合起來,如下:
function fn(){ var numList = [].slice.call(arguments); var _fn = function(){ // 注意這里的 arguments 是傳入 _fn 的參數(shù) var innerArguments = [].slice.call(arguments); numList = numList.concat(innerArguments); console.log(numList); return _fn; } _fn.valueOf = function(){ return 12345; } return _fn; } console.log(fn(1)(2)(3)); // [1, 2, 3]
當(dāng)然,這里也可以使用 push() 的方式,將每一次的參數(shù)推入數(shù)組。
第五步:求和計算這一步還有另一種思路:用每一次的求和代替參數(shù)數(shù)組的合并。
既然已經(jīng)得到了全部的參數(shù)集合,對其進(jìn)行求和就比較簡單了。最直接的方式當(dāng)然是遍歷數(shù)組并累加得到結(jié)果,也可以使用數(shù)組的 reduce 方法實現(xiàn),如下:
var arr = [1, 2, 3]; var sum = arr.reduce(function(num1, num2){ return num1 + num2; }); console.log(sum); // 6
結(jié)合第四步,替換 valueOf 中的返回值即可:
function fn(){ var numList = [].slice.call(arguments); var _fn = function(){ var innerArguments = [].slice.call(arguments); numList = numList.concat(innerArguments); return _fn; } _fn.valueOf = function(){ return numList.reduce(function(num1, num2){ return num1 + num2; }); } return _fn; } console.log(fn(1)(2)(3));
將其進(jìn)行簡化,得到最終結(jié)果:
function fn(){ var numList = [].slice.call(arguments); var _fn = function(){ numList = numList.concat([].slice.call(arguments)); return _fn; } _fn.valueOf = function(){ return numList.reduce(function(i, j){return i+j;}); } return _fn; }
參考當(dāng)然,采用這種實現(xiàn)方式,對于形如 fn(1, 2, 3)(4)(5, 6, 7) 的調(diào)用方式也是沒有問題的。
前端基礎(chǔ)進(jìn)階(八):深入詳解函數(shù)的柯里化 - 簡書
JS中的call()和apply()方法 - ITeye
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/81858.html
摘要:忍者秘籍一書中,對于柯里化的定義如下在一個函數(shù)中首先填充幾個參數(shù)然后再返回一個新函數(shù)的技術(shù)稱為柯里化。回到我們的題目本身,其實根據(jù)測試用例我們可以發(fā)現(xiàn),函數(shù)的要求就是接受單一函數(shù),例如但是與柯里化不同之處在于,柯里化返回的一個新函數(shù)。 歡迎大家再一次來到我的文章專欄:從面試題中我們能學(xué)到什么,各位同行小伙伴是否已經(jīng)開始了悠閑的春節(jié)假期呢?在這里提前祝大家雞年大吉吧~哈哈,之前有人說...
摘要:原題如下寫一個方法,當(dāng)使用下面的語法調(diào)用時,能正常工作這道題要考察的,就是對函數(shù)柯里化的理解。當(dāng)參數(shù)只有一個的時候,進(jìn)行柯里化的處理。這其實就是函數(shù)柯里化的簡單應(yīng)用。 showImg(https://segmentfault.com/img/bVbopGm?w=620&h=350); 前言 這是前端面試題系列的第 6 篇,你可能錯過了前面的篇章,可以在這里找到: ES6 中箭頭函數(shù)的...
摘要:里也有柯里化的實現(xiàn),只是平時沒有在意。如果函數(shù)柯里化后雖然生搬硬套,不過現(xiàn)實業(yè)務(wù)也會有類似場景。 柯里化 先解釋下什么是 柯里化 在計算機科學(xué)中,柯里化(英語:Currying),又譯為卡瑞化或加里化,是把接受多個參數(shù)的函數(shù)變換成接受一個單一參數(shù)(最初函數(shù)的第一個參數(shù))的函數(shù),并且返回接受余下的參數(shù)而且返回結(jié)果的新函數(shù)的技術(shù)。 js 里也有柯里化的實現(xiàn),只是平時沒有在意。先把原文簡介貼...
摘要:函數(shù)式編程的定義函數(shù)是一段可以通過其名稱被調(diào)用的代碼。純函數(shù)大多數(shù)函數(shù)式編程的好處來自于編寫純函數(shù),純函數(shù)是對給定的輸入返回相同的輸出的函數(shù),并且純函數(shù)不應(yīng)依賴任何外部變量,也不應(yīng)改變?nèi)魏瓮獠孔兞俊? 一個持續(xù)更新的github筆記,鏈接地址:Front-End-Basics,可以watch,也可以star。 此篇文章的地址:JavaScript函數(shù)式編程入門經(jīng)典 正文開始 什么是函...
摘要:柯里化函數(shù)的作用函數(shù)柯里化允許和鼓勵你分隔復(fù)雜功能變成更小更容易分析的部分。指向的是調(diào)用方法的一個函數(shù),綁定,延遲執(zhí)行可見,之后返回的是一個延遲執(zhí)行的新函數(shù)關(guān)于性能的備注通常,使用柯里化會有一些開銷。 引子 有這樣一道題目,實現(xiàn)一個函數(shù),實現(xiàn)如下功能: var result = sum(1)(2)(3); console.log(result);//6 這道題目,印象中是一道技術(shù)筆試...
閱讀 3622·2023-04-26 02:44
閱讀 1695·2021-11-25 09:43
閱讀 1657·2021-11-08 13:27
閱讀 1987·2021-09-09 09:33
閱讀 974·2019-08-30 15:53
閱讀 1834·2019-08-30 15:53
閱讀 2834·2019-08-30 15:53
閱讀 3178·2019-08-30 15:44