防抖其实是延迟函数的执行,只有当等待了一段时间也没有事件触发时,才会真正去执行函数
function debounce(func, delay) {
let timer
return function (...args) {
clearTimeout(timer)
timer = setTimeout(() => {
func.apply(this, args)
}, delay)
}
}
节流函数是以固定的频率去触发需要执行的函数,无论请求多少次,在一定时间内只会响应一次。
function throttle(func, delay) {
let lastTime = 0
return function (...args) {
const now = new Date().getTime()
if (now - lastTime >= delay) {
func.apply(this, args)
lastTime = now
}
}
}
function deepCopy(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj
}
let copy
if (Array.isArray(obj)) {
copy = []
for (let i = 0; i < obj.length; i++) {
copy[i] = deepCopy(obj[i])
}
} else {
copy = {}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepCopy(obj[key])
}
}
}
return copy
}
call,apply,bind函数
相同点:
都是改变this的指向
不同点:
call和apply改变了函数的this上下文后便执行该函数
而bind则是返回改变了上下文后的一个函数。
call与apply最大的就是参数的区别,apply接收的是一个数组
Function.prototype._call = function(context, ...args) {
// 如果context不传,this就默认绑定到window
const ctx = context || window;
// 这里this指调用函数
ctx.fn = this;
// 立即执行方法
const res = ctx.fn(...args);
delete ctx.fn; // 为何要delete? 不删则绑定的ctx对象会添加一个fn方法进来可能产生副作用
return res;
}
Function.prototype._apply = function(context, args) {
// 如果context不传,this就默认绑定到window
const ctx = context || window;
// 这里this指调用函数
ctx.fn = this;
// 这里参数为数组
const res = ctx.fn(...args);
delete ctx.fn;
return res;
}
Function.prototype._bind = function(context, ...args) {
// 如果context不传,this就默认绑定到window
const ctx = context || window;
ctx.fn = this;
return function(...subArgs) {
const res = ctx.fn(...args.concat(subArgs))
delete ctx.fn;
return res;
}
}
Promise主要解决回调地域以及异步实现不统一的问题
class MyPromise {
constructor(executor) {
this.state = 'pending'
this.value = undefined
this.onResolveCallbacks = []
this.onRejectCallbacks = []
const resolve = value => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.value = value
this.onResolveCallbacks.forEach(callback => callback(this.value))
}
}
const reject = reason => {
if (this.state === 'pending') {
this.state = 'rejected'
this.value = reason
this.onRejectCallbacks.forEach(callback => callback(this.value))
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onResolve, onReject) {
const newPromise = new MyPromise((resolve, reject) => {
const handleResolve = value => {
try {
const result = onResolve(value)
if (result instanceof MyPromise) {
result.then(resolve, reject)
} else {
resolve(result)
}
} catch (error) {
reject(error)
}
}
const handleReject = reason => {
try {
const result = onReject(reason)
if (result instanceof MyPromise) {
result.then(resolve, reject)
} else {
reject(result)
}
} catch (error) {
reject(error)
}
}
if (this.state === 'fulfilled') {
setTimeout(() => {
handleResolve(this.value)
}, 0)
}
if (this.state === 'rejected') {
setTimeout(() => {
handleReject(this.value)
}, 0)
}
if (this.state === 'pending') {
this.onResolveCallbacks.push(() => {
setTimeout(() => {
handleResolve(this.value)
}, 0)
})
this.onRejectCallbacks.push(() => {
setTimeout(() => {
handleReject(this.value)
}, 0)
})
}
})
return newPromise
}
catch(onReject) {
return this.then(null, onReject)
}
finally(onFinally) {
return this.then(
data => {
onFinally()
return data
},
err => {
onFinally()
throw err
}
)
}
static resolve(value) {
if (value instanceof MyPromise) return value
return new MyPromise(resolve => {
resolve(value)
})
}
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason)
})
}
}