文章轉(zhuǎn)載自公眾號(hào):藍(lán)色的秋風(fēng)
前言
最近學(xué)弟去面了字節(jié)跳動(dòng),但是由于面試經(jīng)驗(yàn)少,面試的時(shí)候緊張了,一時(shí)之間沒有寫出來,之后來我交流了一下。那我就來分析分析這道題目。
正文
這題的規(guī)則是這樣的
給定有一個(gè) Add 函數(shù),要支持以下形式的調(diào)用
Add(1)(2)(3).sumOf(); // 輸出 6
Add(1,2)(3)(4).sumOf(); // 輸出 10
Add(1,2,...)(3)(4)(...).sumOf(); // ...
拿到這種題目,我先來說說我自己的做題流程,一般會(huì)去找它最簡(jiǎn)單的形態(tài)。我們一步一步來拆解。
先去掉 sumOf()
變成了以下形態(tài)
Add(1,2,...)(3)(4)(...)
嗯....有點(diǎn)熟悉...但是還是有點(diǎn)復(fù)雜,那我們?cè)偃サ魺o限調(diào)用這個(gè)限制。
Add(1,2,...)(3)(4)
唔,還是有點(diǎn)難呀...沒關(guān)系,再砍, 不要傳入多個(gè)參數(shù)。
Add(1)(2)(3)
有....有....有那味了....這....這不就是柯里化嗎....
有些小朋友可能沒有聽過,對(duì)于大朋友而言耳熟能詳,融會(huì)貫通。
我們還是來介紹一下。
在《javascript高級(jí)程序設(shè)計(jì)》這本書中有如下介紹:
與函數(shù)綁定緊密相關(guān)的主題是函數(shù)柯里化,它用于創(chuàng)建已經(jīng)設(shè)置好的一個(gè)或者多個(gè)參數(shù)的函數(shù)。函數(shù)柯里化的基本方法和函數(shù)綁定是一樣的:使用一個(gè)閉包返回一個(gè)函數(shù)。兩者的區(qū)別在于,當(dāng)函數(shù)被調(diào)用時(shí),返回的函數(shù)還需要設(shè)置一些傳入的參數(shù)。
我們來寫寫看:
function Add(x) {
return function (y) {
return return functio (z) {
return x + y + z;
}
}
}
// 簡(jiǎn)潔寫法
const Add = x => y => z => x+y+z;
執(zhí)行一下
Add(1)(2)(3) // 6
是我們要的那味~
那么我們既然已經(jīng)寫出了這個(gè)形態(tài),我們就一步一步反推。
這個(gè)時(shí)候千萬別緊張,我們從最低級(jí)的形態(tài)出發(fā),寫出一個(gè)最基本的形態(tài),能夠有效地幫助我們建立自信心,吃下定心丸,按照這種方式,哪怕我們最終沒有寫出完美的結(jié)果,讓面試官看到你思考解題的過程,也是一種加分。
好,接著說~
那我們接下來需要實(shí)現(xiàn)這個(gè)樣子。
Add(1,2,...)(3)(4)
傳入?yún)?shù)不止一個(gè)
我們知道,對(duì)于不確定參數(shù)個(gè)數(shù),我們可以使用 arguments
這個(gè)對(duì)象來獲取到所有的入?yún)ⅲ?arguments
不是一個(gè) Array
,但是我們可以使用 ES6 中的 Spread syntax (展開語(yǔ)法)去將他變成一個(gè)數(shù)組。表演繼續(xù)。
function Add() {
const nums = [...arguments];
return function() {
nums.push(...arguments);
return function() {
nums.push(...arguments);
return nums.reduce((a, b) => a + b);
}
}
}
nice!已經(jīng)離我們最終的形態(tài)越來越近了。接下來是這個(gè)函數(shù)能夠無限的進(jìn)行調(diào)用。
Add(1,2,...)(3)(4)(...)
那么怎么樣才能無限調(diào)用呢?沒錯(cuò),用遞歸。
function Add() {
const nums = [...arguments];
function AddPro() {
nums.push(...arguments);
return AddPro;
}
return AddPro;
}
嗯,其實(shí)我們寫到這里發(fā)現(xiàn)了... 由于是無限遞歸,我們沒辦法確定最后一次函數(shù)調(diào)用,因此我們需要最后顯式調(diào)用一個(gè)結(jié)束的方法來打印出最后的數(shù)據(jù)。
很自然地,我們可以在 AddPro
添加一個(gè)方法 sumOf
來解決這個(gè)問題。
學(xué)弟就是卡在這里地方,被函數(shù)添加上一個(gè)方法搞懵了。你是否知道呢?
function Add() {
const nums = [...arguments];
function AddPro() {
nums.push(...arguments);
return AddPro;
}
AddPro.sumOf = () => {
return nums.reduce((a, b) => a + b);
}
return AddPro;
}
好啦好啦,結(jié)束啦。
等等
在最后,我再來補(bǔ)充一種方案,function
不僅可以繼續(xù)掛載 function
~ 還可以掛載變量哦~
function Add() {
if (!Add.nums) {
Add.nums = [];
}
Add.nums.push(...arguments);
return Add;
}
Add.sumOf = () => {
return Add.nums.reduce((a, b) => a + b);
}
我們總結(jié)一下,小小的面試題涉及到的基礎(chǔ)知識(shí)。
閉包、遞歸、作用域、函數(shù)與對(duì)象
基礎(chǔ)就是基礎(chǔ),永遠(yuǎn)是你爸爸,掌握好基礎(chǔ),以不變應(yīng)萬變。
后記
也許你覺得這題有點(diǎn)簡(jiǎn)單,通過簡(jiǎn)單的重復(fù)練習(xí)就能輕松記住,但是最主要的是思路,很多事情都是一樣,掌握事情的方法和方向是最重要的。畢竟淘寶也不是一蹴而就的~ 但是只要方向正確了,都會(huì)好起來的。
以上就是W3Cschool編程獅
關(guān)于(Add sumOf)一道字節(jié)前端原題的相關(guān)介紹了,希望對(duì)大家有所幫助。