jiangjiu / blog-md

前端/健身 思考与笔记~
https://github.com/jiangjiu/blog-md/issues
86 stars 6 forks source link

小米的两道闭包面试题 #20

Open jiangjiu opened 8 years ago

jiangjiu commented 8 years ago

小米的两道闭包面试题 有点意思~

网上看到了这两道题,都挺有意思的,记录~

repeat 函数

// 题目要求!

function repeat (func, times, wait) {
}
// 这个函数能返回一个新函数,比如这样用
var repeatedFun = repeat(alert, 10, 5000)
调用这个 repeatedFun ("hellworld")
会alert十次 helloworld, 每次间隔5秒

网上给的是 setInterval 的写法,不过考虑到 setInterval 返回值容易忽忽悠悠,还是用 setTimeout来写。

function repeat(func, times, wait) {
    return function () {
      var num = 0;
      // 保存传参, 以便在 handler 中使用
      var _arguments = arguments

      function handler() {
        // 注意此处次数
        if (num < times) {
        num++
          func.apply(null, _arguments)
          setTimeout(handler, wait)
        }
      }

      setTimeout(handler, wait)
    }
  }

这个题考察了闭包和 setTimeout 模拟 setInterval 的用法,因为最终要在 handler 方法中执行func,所以要保存 arguments 对象以便下面的闭包函数调用。

次数也踩了坑,递归调用一定要注意终止条件,本来 num++写在 if 之外,觉得不太妥当,还是放在里面。

stringconcat 函数

// 题目要求!
var result1 = stringconcat("a", "b")  //result1 = "a+b"
var stringconcatWithPrefix = stringconcat.prefix("hellworld");
var result2 = stringconcatWithPrefix("a", "b")  // result2 = "hellworld+a+b"

一看就比第一个复杂。答案还写了 merge 函数,还有 for 循环什么的,测试用例看起来并没有这么复杂, so给出自己的答案。

 function stringconcat() {
    return Array.prototype.slice.call(arguments).join('+')
  }

  stringconcat.prefix = function (str) {
    return function () {
    // 这个 str参数挺有意思的
      var arr = [str].concat(Array.prototype.slice.call(arguments))
      return stringconcat.apply(null, arr)
    }
  }

看似 stringconcat.prefix()返回的只是一个 function,但实际还是保存了外层传进来的参数形成闭包。

另一个坑就是 return function(){}中,不要忘记把 stringconcat.apply的结果 return 回去,一开始我因为没有加 return 导致折腾了一下午!!!

参考

分享小米的两道面试题