防抖,节流。
- 防抖经常出现在用户提交表单上。当网速慢的时候,用户得不到第一时间的反馈就可能在次点击。造成二次发送请求。可能直接导致失败。这个时候可以在点击事件上外加一层防抖函数。具体思路就是当一段时间内如果用户再次点击的话将之前的事件取消。来消除事件多次执行而失败的目的。
function debounce(fn, wait) {
let timer
return (...args) => {
if(timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, args)
}, wait)
}
}
- 节流就是在一段事件内事件只可以触发一次。例如轮播图的滚动问题,多次点击只有第一次点击是有效的
function throttle(fn, wait) {
let timer
return (...args) => {
if(timer) return
timer = setTimeout(() => {
fn.apply(this, args)
}, wait)
}
}
经典的promise
- promise是面试的必问题,手写一个promise可以更好的理解。一个promise主要就是状态,不同状态的回调函数放在一个栈中维护
class newProm {
static resolve(val) {
if(val && val.then) {
return val
}
return new newProm((resolve) => resolve(val))
}
constructor(fn) {
this.status = 'PENDING'
this.value = undefined
this.reason = undefined
this.resolveFns = []
this.rejectFns = []
const resolve = (value) => {
setTimeout(() => {
this.status = 'RESOLVED'
this.value = value
this.resolveFns.forEach(({ fn, resolve: res, reject: rej }) => res(fn(value)))
})
}
const reject = (e) => {
setTimeout(() => {
this.status = 'REJECTED'
this.reason = e
this.rejectFns.forEach(({ fn, resolve: res, reject: rej }) => rej(fn(e)))
})
}
fn(resolve, reject)
}
then(fn) {
if (this.status === 'RESOLVED') {
const result = fn(this.value)
return newProm.resolve(result)
}
if (this.status === 'PENDING') {
return new newProm((resolve, reject) => {
this.resolveFns.push({ fn, resolve, reject })
})
}
}
catch (fn) {
if (this.status === 'REJECTED') {
const result = fn(this.value)
return newProm.resolve(result)
}
if (this.status === 'PENDING') {
return new newProm((resolve, reject) => {
this.rejectFns.push({ fn, resolve, reject })
})
}
}
}
call, apply , bind
Function.prototype.newCall = function (context) {
let context = context || window;
context.fn = this;
let args = [];
let len = arguments.length
for(var i = 1; i < len; i++) {
args.push('arguments[' + i + ']');
}
let result = eval('context.fn(' + args +')');
delete context.fn
return result; 返回结果
}
Function.prototype.newApply = function (context, arr) {
let context = context || window
context.fn = this
let result
let args = []
let len = arr.length
for (var i = 0
args.push('arr[' + i + ']')
}
result = eval('context.fn(' + args + ')')
delete context.fn
return result
}
- bind() 方法会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。
Function.prototype.newBind = function (context) {
if (typeof this !== "function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var fNOP = function () {};
var fbound = function () {
self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments)));
}
fNOP.prototype = this.prototype;
fbound.prototype = new fNOP();
return fbound;
}