前端面试最后算法题
1、实现 Array.prototype.fill(value[,start,[,end]])方法
// 在写这个题目之前我还没有使用过这个方法,使用就在做题中随便是用来一下,发现是改变指定位置所有值的一个方法
function fill(value, start, end) {
if (this == undefined) {
console.log('this is null or undefined');
return;
}
end = end || this.length;
if (start < 0) {
start = this.length + start;
}
if (end > this.length) {
end = this.length;
}
if (end < 0) {
end = this.length + end;
}
for (let i = start; i < this.length; i++) {
this[i] = value;
}
return this;
}
2、实现节流防抖
// 事件只在触发的N秒内,如果没有再次触发,则N秒后触发函数,input
// 防抖
export function debounce(fn, delay = 500) {
let timer;
return function () {
let args = arguments;
if (timer) {
// clearTimeout 是立刻暂停了定时器,但是不会清除对象本身
clearTimeout(timer);
}
timer = setTimeout(() => {
// timer = null 是清除对象本身,但是如果定时器已经开始执行,=null 也无法阻止本次执行
timer = null;
fn.apply(this, args);
}, delay);
};
}
// 事件在一定时间间隔内只执行一次,resize,scroll
// 节流:整个节流都有个最重要得特性,那就是闭包,闭包可以把函数里面得作用域带出来,这样可以让每次得start或者timer都是记忆得同一个得
export function throttleDouble(fn, millisecond) {
let timer;
let start = Date.now();
return function () {
let end = Date.now();
let duration = millisecond - (end - start); // 获取执行时间间隔
clearTimeout(timer);
if (duration <= 0) {
// 执行这个函数
fn.apply(this, arguments);
// 重新赋值这个开始时间
start = end;
} else {
timer = setTimeout(() => {
fn.apply(this, arguments);
}, duration);
}
};
}
3、简单实现发布订阅模式
(function () {
let List = {},
listen,
trigger,
remove;
listen = function (key, fn) {
// 判断如果这个key值还有没有存过,就把他先办成数组,这个就好push不然是undefined
if (!List[key]) {
List[key] = [];
}
// 将函数加进去
List[key].push(fn);
};
trigger = function () {
// 拿到传递进来的第一个参数
let key = Array.prototype.shift.call(arguments);
fns = List[key];
// 判断条件有没有函数在里面
if (!fns || fns.length == 0) {
return false;
}
// 找到所有的函数触发
for (let i = 0, fn; (fn = fns[i++]); ) {
fn.apply(this, arguments);
}
};
remove = function (key, fn) {
let fns = List[key];
if (!fns) {
return false;
}
if (!fn) {
fns && (fns.length = 0);
} else {
// 找到对应的删除
for (let i = fns.length - 1; i >= 0; i--) {
let _fn = fns[i];
if (_fn === fn) {
fns.splice(i, 1);
}
}
}
};
})();