https://bfe.dev 是一个针对前端的刷题网站,像是前端的LeetCode。该系列文章是我在上面的刷题日记。
题目 2
实现curry() 并支持placeholder. implement curry() with placeholder support
分析 & 代码
和第一问 #1. implement curry() 不同的地方就是对于placeholder的处理,我们先看看example
curriedJoin(1, 2, 3) // '1_2_3'
curriedJoin(_, 2)(1, 3) // '1_2_3'
curriedJoin(_, _, _)(1)(_, 3)(2) // '1_2_3'
也就是说,后来的参数需要放置在之前的placeholder的地方。
大概想法和第一问是一样的,除了在判断参数是否够用的时候,需要过滤掉placeholder. 像这样:
const expectedArgLength = func.length
const isArgsEnough = args.length >= expectedArgLength &&
args.slice(0, expectedArgLength)
.every(arg => arg !== curry.placeholder)
if (isArgsEnough) {
return func.apply(this, args)
} else {
// TODO
}
如果参数不够,和之前一样我们需要把参数和后来调用的参数合并在一起,再递归。
但是 Function.prototype.bind
只能简单地按前后顺序concat,所以这里我们不用bind,而是自己寻找placeholder然后merge。
if (isArgsEnough) {
return func.apply(this, args)
} else {
return function(...newArgs) {
// we need merge two arg list, newArgs and args
const finalArgs = []
let i = 0
let j = 0
while (i < args.length && j < newArgs.length) {
if (args[i] === curry.placeholder) {
finalArgs.push(newArgs[j])
i += 1
j += 1
} else {
finalArgs.push(args[i])
i += 1
}
}
while (i < args.length) {
finalArgs.push(args[i])
i += 1
}
while (j < newArgs.length) {
finalArgs.push(newArgs[j])
j += 1
}
// then just call the curried function again
return curried(...finalArgs)
}
}
nice,通过了!
最后
第二问比第一问 BFE.dev#1. implement curry() 要难一些。有兴趣的话你也可以挑战一下。
感谢阅读,希望能有些帮助,下次见。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。