最近公司部门被裁了,让我这个刚刚毕业一年不到的人情何以堪啊。硬着头皮出去面试吧!
在此记录一下今日头条面试中印象比较深刻的问题,问题顺序已打乱。
一、实现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)
当然不止这些题目,我这里只是列出了一些我答得不好和根本没有答出来的题目(逃),面试的结果应该是黄了。今天回头一想其实都还是可以做出来的,只是平时练得太少,心态也有点问题。多多复习,希望接下来的面试顺利吧!