这章学习目标:
提示:以下是本篇文章正文内容,下面案例可供参考
对于字符串类型,浅复制是对值的复制,对于对象来说,浅复制是对对象地址的复制,并没有开辟新的栈,也就是复制的结果是对两个对象指向同一个地址,修改其中一个对象的属性,则另外一个对象的属性也会改变。简单的来说,拷贝的是地址。
拷贝对象之后,里面的属性值是简单数据类型直接拷贝值
如果属性值是引用数据类型则拷贝的是地址
// 一个pink对象
const pink ={
name:'pink老师',
age:18
}
const red = pink
console.log(red)//{name:'pink老师',age:18}
red.name='red老师'
console.log(red)//{name:'red者师',age:18}
//但是pink对象里面的name值也发生了变化
console.log(pink)//[name:'red老师',age:18}
⭕️常用方法
拷贝对象:Object.assign() 或者展开符 {…obj } 拷贝对象
const obj = {
uname: 'pink',
age: 18
}
const o = obj
console.log("o",o)
o.age = 20
console.log(" o.age",o)
console.log("obj",obj)
const obj = {
uname: 'pink',
age: 18
}
const o = {}
Object.assign(o, obj)
o.age = 20
o.family.baby = '老pink'
console.log(o)
console.log(obj)
拷贝数组:Array.prototype.concat() 或者[…arr]
✅ 直接赋值的方法,只要是对象,都会相互影响,因为是直接拷贝对象栈里面的地址。
✅ 浅拷贝如果是一层对象,不相互影响,如果出现多层对象拷贝还会相互影响,
⭕️ 常见方法:
如果一个函数在内部可以调用其本身,那么这个函数就是递归函数
必须要加退出条件 return
let i = 1
function fn() {
console.log(`这是第${i}次`)
if (i >= 6) {
return
}
i++
fn()// 函数内部调用自己
}
fn()
2. js库lodash 里clone Deep内部实现深拷贝
<!-- 先引用 -->
<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)
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)
异常处理是指预估代码执行过程中可能发生的错误,然后最大程度的避免错误的发生导致整个程序无法继续运行。
function counter(x,y){
if(!x||!y){
throw new Error('参数不能为空')
}
return x+y
}
counter()
function fn() {
try {
// 可能预估有问题的代码写到这里
const p = document.querySelector('.p')
p.style.color = 'red'
} catch (err) {
console.log(err.message)
// 中断
// return
throw new Error('你是不是把选择器写错了')
} finally {
alert('执行')
}
console.log(111)
}
fn()
我们可以通过try / catch 捕获错误信息(浏览器提供的错误信息)
不同的应用场合 this 的取值可能会有意想不到的结果,在此我们对以往学习过的关于【 this 默认的取值】情况进行归纳和总结。知道动态指定函数 this 值的方法。
this指向
1️⃣普通函数this指向普通函数的调用方法决定了this的值,即【谁调用this 就指向谁】
// 普通函数: 谁调用我,this就指向谁
1. console.log(this) // window
function fn() {
console.log(this) // window
}
window.fn()
window.setTimeout(function () {
console.log(this) // window
}, 1000)
2.document.querySelector('button').addEventListener('click', function () {
console.log(this) // 指向 button
})
3.const obj = {
sayHi: function () {
console.log(this) // 指向 obj
}
}
obj.sayHi()
this指向
2️⃣ 箭头函数this指向箭头函数中的 this 与普通函数完全不同,也不受调用方式的影响,事实上箭头函数中并不存在 this
1.
console.1og(this)//此处为window
//箭头函数
const sayHi = function(){
console.log(this)
//该箭头函数中的this为函数声明环境中this一致
}
2. //普通对象
const user={
name:'小明',
//该箭头函数中的this为函数声明环境中this一致
walk:()=>{
console.log(this)
}
}
【使用箭头函数前需要考虑函数中 this 的值】,事件回调函数使用箭头函数时,this为全局的window
因此DOM 事件回调函数如果里面需要DOM对象的this,则不推荐使用箭头函数。
//D0M 节点
const btn=document.queryselector('.btn')
//箭头函数此时this指向了window
btn.addEventListener('click',()=>
console.log(this)
})
//普通函数此时this指向了DoM对象
btn.addEventListener('click',function (){
console.log(this)
})
同样由于this的原因,原型的对象不推荐采用箭头函数。
JavaScript 允许指定函数中this 的指向,有3个方法可以动态指定普通函数中 this 的指向
使用call 方法调用函数,同时指定被调用函数中 this 的值。
fun.call(thisArg, arg1, arg2, ...)
thisArg:在fun 函数运行时指定的this值
arg1,arg2:传递参数
返回值就是函数的返回值,因为它就是调用函数。
const obj = {
uname: 'pink'
}
function fn(x, y) {
console.log(this) // window.object
console.log(x + y)// 3
}
// 1. 调用函数
// 2. 改变 this 指向
fn.call(obj, 1, 2)
使用 apply 方法调用函数,同时指定被调用函数中 this 的值。
fn.apply(this指向谁, [数组参数])
const obj = {
age: 18
}
function fn(x, y) {
console.log(this) // Object{age: 18}
console.log(x + y)// 3
}
fn.apply(obj, [1, 2])
// 返回值 本身就是在调用函数,所以返回值就是函数的返回值
thisArg:在fun函数运行时指定的 this 值
argsArray:传递的值,必须包含在数组里面
返回值就是函数的返回值。因为它就是调用函数
apply 主要跟数组有关系,比如使用Math.max() 求数组的最大值。
1.const max = Math.max(1,2,3)
2.const arr =[100 , 45 ,55]
const max =Math.math.apply(Math,arr)
const min =Math.math.apply(Matg,arr)
console.log(max,min)
3. console.log(Math.max(...arr))
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()
注:bind
方法创建新的函数,与原函数的唯一的变化是改变了 this
的值。
节流就指连续触发事件但是在n秒中只执行一次函数。就如等到上一个人完成动作,才能进行下一个人执行。
开发使用场景 – 小米轮播图点击效果 、 鼠标移动、页面尺寸缩放resize、滚动条滚动 就可以加节流。
如果一张轮播图完成切换需要300ms,不加节流效果,快速点击,就会快速切换。
防抖就是触发事件后在n秒内函数只能执行一次,如果在n秒内再次触发事件,则会重新计算。
开发使用场景- 搜索框防抖
假设输入就可以发送请求,但是不能每次输入都去发送请求,输入比较快发送请求会比较多,我们设定一个时间,假如300ms, 当输入第一个字符时候,300ms后发送请求,但是在200ms的时候又输入了一个字符,则需要再等300ms 后发送请求。
lodash文档
<div class="box"></div>
<script src="./lodash.min.js"></script>
function mouseMove() {
box.innerHTML = ++i
// 如果里面存在大量操作 dom 的情况,可能会卡顿
}
box.addEventListener('mousemove', mouseMove)
// lodash 节流写法
box.addEventListener('mousemove', _.throttle(mouseMove, 500))
// lodash 防抖的写法
box.addEventListener('mousemove', _.debounce(mouseMove, 500))
本章深入学习里this学习,知道如何判断this指向和改变this指向,深浅拷贝,递归等知识点,在面试备考中希望能帮助到大家❤️