前端开发Web前端之路前端

记一次今日头条前端面试

2018-05-05  本文已影响85人  钟泽方

最近公司部门被裁了,让我这个刚刚毕业一年不到的人情何以堪啊。硬着头皮出去面试吧!
在此记录一下今日头条面试中印象比较深刻的问题,问题顺序已打乱。

一、实现Bind函数

其实本来不是考查这个的,仅仅是考查bind的用法。后来题目做出来面试官又继续问如何实现bind。下面是参考MDN的polyfill写出来的代码:

if(!Function.prototype.bind){
  Function.prototype.bind = function(context){
    // 首先判断this是不是function
    if(typeof this !== 'function'){
      // 抛出错误
    }
    var _this = this,
          fNOP = function(){},    // 用于后面维护原型关系
          args = Array.prototype.slice.call(arguments, 1),    // 取出bind收到的参数,除去第一个作为上下文的参数并保存
          fBound = function(){
            _this.call(context, args.concat(Array.prototype.slice.call(arguments)))   // 将bind接收的的参数和实际接收到的参数相连接
          };
    // 维护原型关系
    if(this.prototype){
        fNOP.prototype = this.prototype;
        fBound.prototype = new fNOP;
    }
    return fBound;
  }
}

二、实现节流函数

有一个高频操作会让函数迅速执行很多次,需要按照下面的时间线图来实现一个节流函数。


节流函数示意图

图是word画的,微信截的图,凑合看吧...图中每一个断点都代码触发了一次函数,但是触发函数时只在奇数时执行,偶数时不执行,断点间的时间间隔为50ms。
根据题意需要的是一个节流函数。刚开始时我是这么实现的:

var throttle = function(fn){
  var timer = null;
  return function(){
    var args = arguments, context = this;
    clearTimeout(timer);
    timer = setTimeout(function(){
      fn.call(context, args)
    }, 100)
  }
}
这跟javascript高级程序设计中的实现方式差不多,其实严格来说这种实现方式并不叫节流函数,而是防抖函数:短时间内多次调用同一函数,只执行最后一次调用。
下面是改进:
var throttle = function(fn){
  var timer = null;
  return function(){
    var args = arguments, context = this;
    if(!timer){
      timer = setTimeout(function(){
        timer = null;
        fn.call(context, args)
      }, 100);
    }
  }
}
如此一来这个功能基本上就可以实现了,但是仍有一个问题,第一次调用的时候函数并没有执行,而是直接从第三次调用开始执行的,那么我们再改进一下,加一个第一次调用时的哨兵即可:
var throttle = function(fn){
  var timer = null, first = true;
  return function(){
    var args = arguments, context = this;
    if(first){
      first = false;
      fn.call(context, args)
    }
    if(!timer){
      timer = setTimeout(function(){
        timer = null;
        fn.call(context, args)
      }, 100);
    }
  }
}

三、穷举组合

实现一个函数,给三个参数,data是整形数组,m和sum都是一个整数,从data中取出n个整数,使它们的和为sum,求出一种组合即可。
我的思路是穷举data中的n个key的组合,假设data有6(n)个元素,从中取出3(m)个数,那么它key的组合就有:[0,1,2]、[0,1,3]、[0,1,4]、[0,1,5]、[0,2,3]、[0,2,4]、[0,2,5]、...、[3,4,5]
列出它的所有组合就好办了,直接用这些key去data里面取数,如果找到答案就退出程序。
下面仅给出穷举组合的算法,为了简单,相关参数写死并忽略全局污染:

// 数组a用于存放key的组合,data并没有出现,只给出data元素个数n
var a=[0,1,2], oldA = [],n = 6, len = a.length;
function listArr(key){
    let same = true
    for(let i = 0 ; i < len ; i++){
        if(a[i] !== oldA[i]){
            same = false
            break
        }
    }
    if(!same){
        console.log(a)
        oldA = Array.prototype.slice.call(a)
    }
}
function list(currentKey, initValue){
    if(currentKey >= len || initValue >= n){
        return
    }
    for(let v = initValue ; v <= n + currentKey - len ; v++){
        a[currentKey] = v
        arguments.callee(currentKey+1, v+1)
        listArr(currentKey);
    }
}
list(0,0)

当然不止这些题目,我这里只是列出了一些我答得不好和根本没有答出来的题目(逃),面试的结果应该是黄了。今天回头一想其实都还是可以做出来的,只是平时练得太少,心态也有点问题。多多复习,希望接下来的面试顺利吧!

上一篇下一篇

猜你喜欢

热点阅读