JavaScript 学习笔记(JS进阶 Day4)

「写在前面」

本文为 b 站黑马程序员 pink 老师 JavaScript 教程的学习笔记。本着自己学习、分享他人的态度,分享学习笔记,希望能对大家有所帮助。推荐先按顺序阅读往期内容:
1. JavaScript 学习笔记(Day1)
2. JavaScript 学习笔记(Day2)
3. JavaScript 学习笔记(Day3)
4. JavaScript 学习笔记(Day4)
5. JavaScript 学习笔记(Day5)
6. JavaScript 学习笔记(WEB APIs Day1)
7. JavaScript 学习笔记(WEB APIs Day2)
8. JavaScript 学习笔记(WEB APIs Day3)
9. JavaScript 学习笔记(WEB APIs Day4)
10. JavaScript 学习笔记(WEB APIs Day5)
11. JavaScript 学习笔记(WEB APIs Day6)
12. JavaScript 学习笔记(JS进阶 Day1)
13. JavaScript 学习笔记(JS进阶 Day2)
14. JavaScript 学习笔记(JS进阶 Day3)


目录

  • 1 深浅拷贝
  • 2 异常处理
  • 3 处理this
  • 4 性能优化
  • 5 综合案例
  • 6 完结撒花

1 深浅拷贝

1.1 浅拷贝

P188:https://www.bilibili.com/video/BV1Y84y1L7Nn?p=188

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

浅拷贝:拷贝的是地址

常见方法:

  1. 拷贝对象: Object.assgin() / 展开运算符 {...obj} 拷贝对象
  2. 拷贝数组: Array.prototype.concat() 或者 [...arr]
const obj = {
uname: 'pink'
}
const o = { ...obj }
console.log(o) // {uname: 'pink'}
o.uname = 'red'
console.log(o) // {uname : 'red'}
console.log(obj) // {uname: 'pink' }

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

// 一个pink对象
const pink = {
name: 'pink老师',
age: 18,
famliy: {
mother: 'pink妈妈'
}
}
const red = {}
object.assign(red, pink)
console.log(red) // {name: 'pink老师', age: 18}
red.name = 'red老师'
// 更改对象里面的 family 还是会有影响
red.famliy.mother = 'red妈妈'
consoie.log(red) // {name: 'red老师', age: 18}
// 不会影响pink对象
console.log(pink) // {name: 'pink老师', age: 18}

1.2 深拷贝

P189:https://www.bilibili.com/video/BV1Y84y1L7Nn?p=189

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

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

常见方法:

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

1. 通过递归实现深拷贝

函数递归:

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

  • 简单理解:函数内部自己调用自己, 这个函数就是递归函数
  • 递归函数的作用和循环效果类似
  • 由于递归很容易发生“栈溢出”错误(stack overflow),所以 必须要加退出条件 return
let num = 1
// fn就是递归函数
function fn() {
console.log('我要打印6次')
if (num >= 6) {
return
}
num++
fn() // 函数内部调用函数自己
}
fn()

P190:https://www.bilibili.com/video/BV1Y84y1L7Nn?p=190

通过递归函数实现深拷贝:

const o = {}
function deepCopy(newObj, oldObj) {
for (let k in old0bj) {
if (oldObj[k] instanceof Array) {
new0bj[k] = []
deepCopy(newObj[k], oldObj[k])
} else if (oldObj[k] instanceof Object) {
newObj[k]= {}
deepCopy(newObj[k], oldObj[k])
}
else {
newObj[k] = old0bj[k]}
}
}
}

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

P191:https://www.bilibili.com/video/BV1Y84y1L7Nn?p=191

const obj = {
uname: 'pink',
age: 18,
hobby: ['篮球', '足球'],
family: {
baby: '小pink'
}
}
// 语法: _.cLoneDeep(要被克隆的对象)
const o = _.cloneDeep(obj)
console.log(o)
o.family.baby = '老pink'
console.log(obj)

3. 通过JSON.stringify()实现

const obj = {
uname: 'pink',
age: 18,
hobby:['篮球', '足球'],
family: {
baby: '小pink'
}
}
const o = JSON.parse(JSON.stringify(obj))
console.log(o)
o.family.baby = '老pink'
console.log(obj)

2 异常处理

2.1 throw 抛异常

P192:https://www.bilibili.com/video/BV1Y84y1L7Nn?p=192

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

  1. throw 抛出异常信息,程序也会终止执行
  2. throw 后面跟的是错误提示信息
  3. Error 对象配合 throw 使用,能够设置更详细的错误信息
function counter(x, y) {
if (!x || !y) {
throw new Error('参数不能为空!”
}
return X + y
}
counter()

2.2 try /catch 捕获异常

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

  1. try...catch 用于捕获错误信息
  2. 将预估可能发生错误的代码写在 try 代码段中
  3. 如果 try 代码段中出现错误后,会执行 catch 代码段,并截获到错误信息
  4. finally 不管是否有错误,都会执行
<p>123p>
<script>
function fn() {
try {
// 可能发送错误的代码要写到 try
const p = document.querySelector('.p')
p.style.color = 'red'
} catch (err) {
// 拦截错误,提示浏览器提供的错误信息,但是不中断程序的执行
console.log(err.message)
throw new Error('你看看,选择器错误了吧')
// 需要加return中断程序
// return
}
finally {
// 不管你程序对不对,一定会执行的代码
alert('弹出对话框')
}
console.log(11)
}
fn()
script>

2.3 debugger

debugger 相当于打断点

JavaScript 学习笔记(JS进阶 Day4)_第1张图片

3 处理this

3.1 this指向

P193:https://www.bilibili.com/video/BV1Y84y1L7Nn?p=193

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

JavaScript 学习笔记(JS进阶 Day4)_第2张图片

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

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

  1. 箭头函数会默认帮我们绑定外层 this 的值,所以在箭头函数中 this 的值和外层的 this 是一样的
  2. 箭头函数中的this引用的就是最近作用域中的this
  3. 向外层作用域中,一层一层查找this,直到有this的定义
alt

注意情况1:

在开发中【使用箭头函数前需要考虑函数中 this 的值】,事件回调函数使用箭头函数时,this 为全局的 window

因此DOM事件回调函数如果里面需要DOM对象的this,则不推荐使用箭头函数

JavaScript 学习笔记(JS进阶 Day4)_第3张图片

注意情况2:

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

JavaScript 学习笔记(JS进阶 Day4)_第4张图片

3.2 改变this

P194:https://www.bilibili.com/video/BV1Y84y1L7Nn?p=194

1. call() –了解

使用 call 方法调用函数,同时指定被调用函数中 this 的值

语法:fun.call(thisArg, arg1, arg2, ...)

  • thisArg:在 fun 函数运行时指定的 this 值
  • arg1,arg2:传递的其他参数
  • 返回值就是函数的返回值,因为它就是调用函数
const obj = {
uname: 'pink'
}
function fn(x, y) {
console.log(this) // windowconsole.log(x +y)
}
// 1.调用函数
// 2. 改变this指向
fn.call(obj, 1, 2)

2. apply()-理解

P195:https://www.bilibili.com/video/BV1Y84y1L7Nn?p=195

使用 apply 方法调用函数,同时指定被调用函数中 this 的值

语法:fun.apply(thisArg, [argsArray])

  • thisArg:在fun函数运行时指定的 this 值
  • argsArray:传递的值,必须包含在数组里面
  • 返回值就是函数的返回值,因为它就是调用函数
  • 因此 apply 主要跟数组有关系,比如使用 Math.max() 求数组的最大值
// 求和函数
function counter(x, y) {
return x + y
}
// 调用 counter 函数,并传入参数
let result = counter.apply(null, [5, 10])
console.log(result)

3. bind()-重点

P196:https://www.bilibili.com/video/BV1Y84y1L7Nn?p=196

bind() 方法不会调用函数。但是能改变函数内部this 指向

语法:fun.bind(thisArg, arg1, arg2, ...)

  • thisArg:在 fun 函数运行时指定的 this 值
  • arg1,arg2:传递的其他参数
  • 返回由指定的 this 值和初始化参数改造的 原函数拷贝 (新函数)
  • 因此当我们只是想改变 this 指向,并且不想调用这个函数的时候,可以使用 bind,比如改变定时器内部的this指向.
// 普通函数
function sayHi() {
console.log(this)
}
let user = {
name: '小明',
age: 18
}
// 调用 bind 指定this的值
let sayHello = sayHi.bind(user);
// 调用使用 bind 创建的新函数
sayHello()

相同点:

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

区别点:

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

主要应用场景:

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

4 性能优化

4.1 防抖

P197:https://www.bilibili.com/video/BV1Y84y1L7Nn?p=197

防抖: 单位时间内,频繁触发事件,只执行最后一次

使用场景:

  • 搜索框搜索输入。只需用户最后一次输入完,再发送请求
  • 手机号、邮箱验证输入检测

4.2 防抖

P198:https://www.bilibili.com/video/BV1Y84y1L7Nn?p=198

节流:单位时间内,频繁触发事件,只执行一次

使用场景:

高频事件:鼠标移动mousemove、页面尺寸缩放resize、滚动条滚动scroll等等

5 综合案例

P199:https://www.bilibili.com/video/BV1Y84y1L7Nn?p=199

6 完结撒花

P200:https://www.bilibili.com/video/BV1Y84y1L7Nn?p=200

感谢这段时间奋斗的自己,
让我们这段时间变得有价值。


「结束」
alt

本文由 mdnice 多平台发布

你可能感兴趣的:(前端,javascript)