1、手动实现防抖
防抖: 对于频繁触发事件,只在最后一次触发生效
// 非立即防抖:持续触发事件时,事件处理函数完全不执行,等最后一次触发结束一段时间后再执行
// 实现思路:每次触发事件时都取消之前的延时调用方法,并重设定时器
function debounce(wait, funct, ...args) {
var timer = null
return () => {
clearTimeout(timer)
timer = setTimeout(() => funct(...args), wait)
}
}
// 立即防抖:持续触发事件时,事件处理函数会立即执行,然后不执行事件处理函数,直至最后一次
// 触发之后的一段时间后才允许再次执行事件处理函数
// 实现思路:判断是否有定时器,没有则执行事件处理函数,然后无论是否有定时器都需重设定时器
function debounce(wait, funct, ...args) {
var timer = null
return () => {
if(!timer) funct(...args)
clearTimeout(timer)
timer = setTimeout(() => timer = null, wait)
}
}
window.onscroll = debounce(300, (a) => console.log(a), 1)
2、手动实现节流
节流:把频繁触发事件变为少量触发
//时间戳实现:通过时间戳记录上次事件处理执行时间,如果和现在时间差大于执行周期,则执行事件
// 处理函数并赋值执行时间为当前时间戳
function throttle(wait, funct, ...args) {
var prev = Date.now()
return () => {
var now = Date.now()
if(now - prev > wait) {
funct(...args)
prev = now
}
}
}
// 定时器实现:判断是否有定时器,没有则执行事件处理函数并重设定时器
function throttle(wait, funct, ...args) {
var timer = null
return () => {
if(!timer) {
funct(...args)
timer = setTimeout(() => timer = null, wait)
}
}
}
window.onscroll = throttle(1000, (a) => console.log(a), 1)
3、手动实现Promise
class Promise {
// 定义Promise构造函数
constructor(excutor) {
this.status = "pending"
this.value = undefined
this.reason = undefined
// 分别存放成功、失败的回调
this.onResolved = []
this.onRejected = []
let handler = funct => {
if(typeof(funct) === "function") {
if(this.status === "fulfilled") funct(this.value)
if(this.status === "rejected") funct(this.reasion)
}
}
// 实现resolve回调
let resolve = value => {
if(this.status === "pending") {
this.status = "fulfilled"
this.value = value
this.onResolved.forEach(handler)
}
}
// 实现reject回调
let reject = reason => {
if(this.status === "pending") {
this.status = "rejected"
this.reason = reason
this.onRejected.forEach(handler)
}
}
try {
excutor(resolve, reject)
} catch(error) {
reject(error)
}
}
// 定义then回调
then(resolved, rejected) {
if(this.status === "fulfilled") {
resolved(this.value)
}
if(this.status === "rejected") {
rejected(this.reason)
}
if(this.status === "pending") {
this.onResolved.push(() => {
resolved(this.value)
})
this.onRejected.push() => {
rejected(this.reason)
})
}
}
}
// 测试promise
const promise = new Promise((resolve,reject) => {
setTimeout(() => {
resolve('成功')
},1000)
}).then(
(data) => {
console.log('success',data);
},
((err) => {
console.log('failed',err);
}
)
4、手动实现Ajax
浏览器的同源策略:协议、url、端口号任一不同都算为跨域请求
function ajax(url, method = "GET", data = null, async = true) {
var XHR = XMLHttpRequest
// 创建XMLHttpRequest对象,考虑兼容性,老版本的IE5、IE6使用ActiveX
XHR = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXobject("Microsoft.XMLHTTP")
XHR.open(method, url, async)
XHR.onreadystatechange = function() {
if(XHR.readyState == 4) {
if(XHR.statuss >=200 && XHR.status<300) {
alert(XHR.requestText)
} else {
alert("ajax服务器返回错误")
}
}
}
XHR.send(data)
}
ajax("https://www.baidu.com", "POST", "A=1&B=2")
// 利用promise封装实现Ajax
function ajax({url='',type = 'get',dataType = 'json'}){
return new Promise((resolve,reject)=>{
let xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXobject("Microsoft.XMLHTTP")
xhr.open(type,url,dataType)
xhr.onReadyStateChange = function(){
if(xhr.readyState === 4){
if(xhr.status >=200 && xhr.status<300){
resolve(xhr.response)
}
}else{
reject(error)
}
}
xhr.send()
})
}