🪐背八股文最好结合实际项目,理解式的记下来
JavaScript
一、手写函数
1. 防抖
function debounce(func, delay, immediate) {
let timer
return function() {
// 闭包
let _this = this
let arg = arguments
if (timer) clearTimeout(timer) // 重复触发,重新开始计时
if (immediate) {
// 立即执行
let callNow = !timer // 定时器是空的,说明可以执行
timer = setTimeout(() => {
// 开始计时
timer = null // 计时结束后将timer置空,下一次立即执行
}, delay);
if (callNow) {
func.apply(_this, arg) }
} else {
// 非立即执行
timer = setTimeout(() => {
func.apply(_this, arg) // 计时结束后执行
}, delay);
}
}
}
// 第三个参数为true表示立即执行,为空或者false表示非立即执行
box.addEventListener('mouseover', debounce(function() {
box.innerHTML = i++
}, 2000, true))
2.节流
// 定时器版
function throttle1(func, wait) {
let pre = 0
return function() {
let _this = this
let arg = arguments
let now = new Date()
if (now - pre > wait) {
func.apply(_this, arg)
pre = now
}
}
}
// 时间戳版
function throttle2(func, wait) {
let timer
return function() {
let _this = this
let arg = arguments
if (!timer) {
timer = setTimeout(() => {
timer = null
func.apply(_this, arg)
}, wait);
}
}
}
box4.addEventListener('mouseover', throttle2(function() {
box4.innerHTML = i4++
}, 1000))
3. 深拷贝
// 先自己写一个判断数据类型的方法
function typeOf(param) {
const res = Object.prototype.toString.call(param).replace(/(\[|\]|object)/g, '').trim().toLowerCase()
return res
}
// 手写深克隆
function deepClone(obj) {
// 首先判断参数是基本数据类型还是引用数据类型
if (typeOf(obj) === 'object' || typeOf(obj) === 'array') {
// 引用数据类型
// 进一步判断是对象还是数组
let newObj = typeOf(obj) === 'object' ? {
} : []
for (let k in obj) {
if (typeOf(obj[k]) === 'object' || typeOf(obj[k]) === 'array') {
newObj[k] = deepClone(obj[k]) // 递归克隆
} else {
newObj[k] = obj[k]
}
}
return newObj
} else {
// 基本数据类型
// 直接返回原数据
return obj
}
}
const decoObj1 = deepClone(obj)
4. 数组去重/数组乱序
数组去重
// 第一种: 6ES的Set方法
res = [...new Set(arr)]
res = Array.from(new Set(arr)) // [12, 20, 13, 5]
// 第二种:循环比较(拿后一项与当前项比较)
for (let i = 0; i < arr.length - 1; i++) {
let cur = arr[i] // 当前项
let args = arr.slice(i +1) // 剩余的项
const index = args.indexOf(cur)
if (index !== -1) {
// 说明有重复的
// 遇到重复的,拿最后一项来替换,这样就不需要每次都改变index,结果 [5, 20, 12, 13]
arr[i] = arr[arr.length - 1]
i-- // 从当前项(原本的最后一项)开始继续比较
arr.length-- // 去掉最后一项
}
}
// 从最后一项开始循环, [12, 20, 13, 5]保证了顺序
for (let i = arr.length-1; i >= 0; i--) {
let cur = arr[i]
let args = arr.slice(0, i)
if (args.indexOf(cur) !== -1) {
// 重复项
arr.splice(i, 1)
}
}
// 第三种:对象法, 顺序不变[12, 20, 13, 5]
let obj = {
}
for (let i = 0; i < arr.length; i++) {
let cur = arr[i