章節連結
在近期的面試中,獲得了一個經典 JavaScript 實作題,解法的思路相當有趣,所以將其筆記下來。
題目
實作 helloSat 這個函式:
helloSat(1, 2); // 3
helloSat(1)(2); // 3
解法
其實這一題網路上常見的版本會是:
add(1,2); // 3
add(1)(2); // 3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
function helloSat(){ let args = [...arguments]; let addFn = function(){ args.push(...arguments); return addFn; } addFn.toString= function(){ return args.reduce((a,b)=>{ return a + b; }); } return addFn; } helloSat(1,2,3)(4) / f 10 helloSat(1,2,3)(4).toString // 10 |
原理
Currying 柯里化
簡言之,利用 JavaScript 的 Closure 閉包特性,將一個接受 n 個參數的函式,變成 n 個只接受一個參數的函式。所以,當一個函式呼叫後,只處理一個參數,再回傳一個函式。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// 兩數乘法 function multiple(x,y){ return x*y } function curryingMultiple(x){ return function(y){ return x * y } } multiple(3,4) // 12 curryingMultiple(3)(4) // 12 |
function 的自動調用
function 在執行到最後的 return 值,會使用 function.toString 的結果,所以可以藉由此一特性,在瀏覽器中的 Console 實現題目要求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// input function helloSat(){ console.log('enter!'); let args = [...arguments]; let addFn = function(){ console.log('調用 addFn'); args.push(...arguments); return addFn; } addFn.toString = function(){ console.log('調用toString') return 222 } return addFn; } helloSat(1)(2)(3,4,5) helloSat(1)(2)(3,4,5).toString() // output ƒ 222 222 |
參考資料
1. Currying in JavaScript(柯里化)
2. 柯里化
3. 一道面试题引发的对javascript类型转换的思考
4. 第 84 题:请实现一个 add 函数,满足以下功能。