BFE.dev前端刷题2 - 实现curry() 并支持placeholder

时间:2022-07-23
本文章向大家介绍BFE.dev前端刷题2 - 实现curry() 并支持placeholder,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

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() 要难一些。有兴趣的话你也可以挑战一下。

感谢阅读,希望能有些帮助,下次见。