ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

JS进阶-高阶技巧

JS进阶-高阶技巧

深浅拷贝

首先浅拷贝和深拷贝只针对引用类型 

• 浅拷贝

开发中我们经常需要复制一个对象。如果直接用赋值会有下面问题:

这好比有同学来pink老师这里拷视频,竟然用的是剪切…气人不

浅拷贝:拷贝的是地址

1. 拷贝对象:Object.assgin() / 展开运算符 {...obj} 拷贝对象

2.拷贝数组:Array.prototype.concat() 或者 [...arr]

 

 

如果是简单数据类型拷贝值,引用数据类型拷贝的是地址 (简单理解: 如果是单层对象,没问题,如果有多层就有问题)

 1. 直接赋值和浅拷贝有什么区别?

  •  直接赋值的方法,只要是对象,都会相互影响,因为是直接拷贝对象栈里面的地址
  •  浅拷贝如果是一层对象,不相互影响,如果出现多层对象拷贝还会相互影响

2. 浅拷贝怎么理解?

  •  拷贝对象之后,里面的属性值是简单数据类型直接拷贝值
  •  如果属性值是引用数据类型则拷贝的是地址

• 深拷贝

深拷贝:拷贝的是对象,不是地址

常见方法:
1. 通过递归实现深拷贝
2. lodash/cloneDeep
3. 通过JSON.stringify()实现

1. 通过递归实现深拷

函数递归:如果一个函数在内部可以调用其本身,那么这个函数就是递归函数

 简单理解:函数内部自己调用自己, 这个函数就是递归函数
 递归函数的作用和循环效果类似
 由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件 return

2. js库lodash里面cloneDeep内部实现了深拷贝 

3. 通过JSON.stringify()实现 

 

异常处理

• throw 抛异常

 异常处理是指预估代码执行过程中可能发生的错误,然后最大程度的避免错误的发生导致整个程序无法继续运行

1. 抛出异常我们用那个关键字?它会终止程序吗?

  • throw 关键字
  • 会中止程序

2. 抛出异常经常和谁配合使用?

  • Error 对象配合 throw 使用 

• try /catch 捕获异常

我们可以通过try / catch 捕获错误信息(浏览器提供的错误信息) try 试试 catch 拦住 finally 最后

• debugger

我们可以通过try / catch 捕获错误信息(浏览器提供的错误信息)

 debugger就相当于打断点,只是它是代码形式的

处理this

• this指向

1. 普通函数this指向

普通函数的调用方式决定了 this 的值,即【谁调用 this 的值指向谁】

普通函数没有明确调用者时 this 值为 window,严格模式下没有调用者时 this 的值为 undefined 

2. 箭头函数this指向

箭头函数中的 this 与普通函数完全不同,也不受调用方式的影响,事实上箭头函数中并不存在 this !

1. 箭头函数会默认帮我们绑定外层 this 的值,所以在箭头函数中 this 的值和外层的 this 是一样的

2.箭头函数中的this引用的就是最近作用域中的this

3.向外层作用域中,一层一层查找this,直到有this的定义

注意情况1: 

在开发中【使用箭头函数前需要考虑函数中 this 的值】,事件回调函数使用箭头函数时,this 为全局的 window 因此DOM事件回调函数如果里面需要DOM对象的this,则不推荐使用箭头函数

注意情况2: 

同样由于箭头函数 this 的原因,基于原型的面向对象也不推荐采用箭头函数

• 改变this 

JavaScript 中还允许指定函数中 this 的指向,有 3 个方法可以动态指定普通函数中 this 的指向

  • call()
  • apply()
  • bind()

 

 

 

call apply bind 总结 

相同点:

  • 都可以改变函数内部的this指向.

区别点:

  • call 和 apply 会调用函数, 并且改变函数内部this指向.
  • call 和 apply 传递的参数不一样, call 传递参数 aru1, aru2..形式 apply 必须数组形式[arg]
  • bind 不会调用函数, 可以改变函数内部this指向.

主要应用场景:

  • call 调用函数并且可以传递参数
  • apply 经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值
  • bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向.

性能优化

• 节流

• 防抖

综合案例

页面打开,可以记录上一次的视频播放位置

分析:
两个事件:
①:ontimeupdate 事件在视频/音频(audio/video)当前的播放位置发送改变时触发
②:onloadeddata 事件在当前帧的数据加载完成且还没有足够的数据播放视频/音频(audio/video)的
下一帧时触发
谁需要节流?
ontimeupdate , 触发频次太高了,我们可以设定 1秒钟触发一次

<!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>

 

返回列表