思维导图
高阶技巧
1. 深浅拷贝
1.1 浅拷贝
1.2 深拷贝
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div></div><script>function getTime() {document.querySelector('div').innerHTML = new Date().toLocaleString()setTimeout(getTime, 1000)}getTime()</script>
</body></html>
递归函数实现深拷贝
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>const obj = {uname: 'pink',age: 18,hobby: ['乒乓球', '足球'],family: {baby: '小pink'}}const o = {}// 拷贝函数function deepCopy(newObj, oldObj) {debuggerfor (let k in oldObj) {// 处理数组的问题 一定先写数组 在写 对象 不能颠倒if (oldObj[k] instanceof Array) {newObj[k] = []// newObj[k] 接收 [] hobby// oldObj[k] ['乒乓球', '足球']deepCopy(newObj[k], oldObj[k])} else if (oldObj[k] instanceof Object) {newObj[k] = {}deepCopy(newObj[k], oldObj[k])}else {// k 属性名 uname age oldObj[k] 属性值 18// newObj[k] === o.uname 给新对象添加属性newObj[k] = oldObj[k]}}}deepCopy(o, obj) // 函数调用 两个参数 o 新对象 obj 旧对象console.log(o)o.age = 20o.hobby[0] = '篮球'o.family.baby = '老pink'console.log(obj)console.log([1, 23] instanceof Object)// 复习// const obj = {// uname: 'pink',// age: 18,// hobby: ['乒乓球', '足球']// }// function deepCopy({ }, oldObj) {// // k 属性名 oldObj[k] 属性值// for (let k in oldObj) {// // 处理数组的问题 k 变量// newObj[k] = oldObj[k]// // o.uname = 'pink'// // newObj.k = 'pink'// }// }</script>
</body></html>
lodash实现深拷贝
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><!-- 先引用 --><script src="./lodash.min.js"></script><script>const obj = {uname: 'pink',age: 18,hobby: ['乒乓球', '足球'],family: {baby: '小pink'}}const o = _.cloneDeep(obj)console.log(o)o.family.baby = '老pink'console.log(obj)</script>
</body></html>
利用JSON实现深拷贝
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>const obj = {uname: 'pink',age: 18,hobby: ['乒乓球', '足球'],family: {baby: '小pink'}}// 把对象转换为 JSON 字符串// console.log(JSON.stringify(obj))const o = JSON.parse(JSON.stringify(obj))console.log(o)o.family.baby = '123'console.log(obj)</script>
</body></html>
2.异常处理
2.1 throw 抛异常
2.2 try/catch 捕获错误信息
2.3 debugger
3.处理this
3.1 this指向
普通函数
箭头函数
3.2 改变this
call()
apply()
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><script>const obj = {age: 18}function fn(x, y) {console.log(this) // {age: 18}console.log(x + y)}// 1. 调用函数// 2. 改变this指向 // fn.apply(this指向谁, 数组参数)fn.apply(obj, [1, 2])// 3. 返回值 本身就是在调用函数,所以返回值就是函数的返回值// 使用场景: 求数组最大值// const max = Math.max(1, 2, 3)// console.log(max)const arr = [100, 44, 77]const max = Math.max.apply(Math, arr)const min = Math.min.apply(null, arr)console.log(max, min)// 使用场景: 求数组最大值console.log(Math.max(...arr))</script>
</body></html>
bind()-重点
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><button>发送短信</button><script>const obj = {age: 18}function fn() {console.log(this)}// 1. bind 不会调用函数 // 2. 能改变this指向// 3. 返回值是个函数, 但是这个函数里面的this是更改过的objconst fun = fn.bind(obj)// console.log(fun) fun()// 需求,有一个按钮,点击里面就禁用,2秒钟之后开启document.querySelector('button').addEventListener('click', function () {// 禁用按钮this.disabled = truewindow.setTimeout(function () {// 在这个普通函数里面,我们要this由原来的window 改为 btnthis.disabled = false}.bind(this), 2000) // 这里的this 和 btn 一样})</script>
</body></html>
4.性能优化
4.1 防抖
lodash提供的防抖处理
_.debounce(mouseMove, 500)
手写防抖
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><style>.box {width: 500px;height: 500px;background-color: #ccc;color: #fff;text-align: center;font-size: 100px;}</style>
</head><body><div class="box"></div><script>const box = document.querySelector('.box')let i = 1 // 让这个变量++// 鼠标移动函数function mouseMove() {box.innerHTML = ++i// 如果里面存在大量操作 dom 的情况,可能会卡顿}// 防抖函数function debounce(fn, t) {let timeIdreturn function () {// 如果有定时器就清除if (timeId) clearTimeout(timeId)// 开启定时器 200timeId = setTimeout(function () {fn()}, t)}}// box.addEventListener('mousemove', mouseMove)box.addEventListener('mousemove', debounce(mouseMove, 200))</script>
</body></html>
4.2 节流
lodash实现节流
手动实现节流
所以使用timer = null 清空定时器
5.综合案例
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="referrer" content="never" /><title>综合案例</title><style>* {padding: 0;margin: 0;box-sizing: border-box;}.container {width: 1200px;margin: 0 auto;}.video video {width: 100%;padding: 20px 0;}.elevator {position: fixed;top: 280px;right: 20px;z-index: 999;background: #fff;border: 1px solid #e4e4e4;width: 60px;}.elevator a {display: block;padding: 10px;text-decoration: none;text-align: center;color: #999;}.elevator a.active {color: #1286ff;}.outline {padding-bottom: 300px;}</style>
</head><body><div class="container"><div class="header"><a href="http://pip.itcast.cn"><img src="https://pip.itcast.cn/img/logo_v3.29b9ba72.png" alt="" /></a></div><div class="video"><video src="https://v.itheima.net/LapADhV6.mp4" controls></video></div><div class="elevator"><a href="javascript:;" data-ref="video">视频介绍</a><a href="javascript:;" data-ref="intro">课程简介</a><a href="javascript:;" data-ref="outline">评论列表</a></div></div><script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script><script>// 1. 获取元素 要对视频进行操作const video = document.querySelector('video')video.ontimeupdate = _.throttle(() => {// console.log(video.currentTime) 获得当前的视频时间// 把当前的时间存储到本地存储localStorage.setItem('currentTime', video.currentTime)}, 1000)// 打开页面触发事件,就从本地存储里面取出记录的时间, 赋值给 video.currentTimevideo.onloadeddata = () => {// console.log(111)video.currentTime = localStorage.getItem('currentTime') || 0}</script>
</body></html>