一、浅拷贝
深拷贝和浅拷贝是指在赋值一个对象时,拷贝的深度不同。
浅拷贝:把对象拷贝给一个新的对象,开发中我们经常需要复制一个对象 如果直接赋值,则复制的是地址,修改任何一个对象,另一个对象都会变化
1. 1 拷贝对象:
1.Object. assign()
2.展开运算符 {...obj}
代码分享:
<!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>浅拷贝-对象拷贝的两种方法</title>
</head>
<body>
<script>
// 浅拷贝方法
// 1. 对象拷贝
const obj = {
name: '佩奇'
}
// 1.1 Object.assign()
const newObj = {}
Object.assign(newObj, obj)
// console.log(newObj)
console.log(newObj === obj) // false
newObj.name = '乔治'
console.log(obj)
console.log(newObj)
// 1.2 展开运算符
const newObj = { ...obj }
console.log(newObj === obj) // false
newObj.name = '乔治'
console.log(obj)
console.log(newObj)
</script>
</body>
</html>
1.2 拷贝数组:
1.Array.prototype.concat()
2.展开运算符 [...arr]
代码分享:
<!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>浅拷贝方法-数组</title>
</head>
<body>
<script>
// 浅拷贝方法
// // 2. 数组拷贝
const arr = ['佩奇', '乔治']
// 2.1 concat 方法实现数组浅拷贝
const arr1 = []
const newArr = arr1.concat(arr)
console.log(newArr)
newArr[1] = '猪爸爸'
console.log(arr)
console.log(newArr)
// 2.2 展开运算符
const newArr = [...arr]
console.log(newArr)
newArr[1] = '猪爸爸'
console.log(arr)
console.log(newArr)
</script>
</body>
</html>
1.3 浅拷贝的问题:
浅拷贝只会拷贝对象的第一层属性,如果这些属性是对象,则不会对这些对象进行拷贝,而是直接复制对象的引用。这意味着,对于浅拷贝后的对象,如果原对象的属性值发生了变化,浅拷贝后的对象的属性值也会跟着发生变化。
代码分享:
<!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>浅拷贝存在的问题</title>
</head>
<body>
<script>
// 浅拷贝方法
// 3. 浅拷贝的问题如果遇到多层拷贝还是会影响原来的对象
const obj = {
name: '佩奇',
family: {
father: '猪爸爸'
}
}
const newObj = { ...obj }
// console.log(newObj)
newObj.family.father = 'dad'
console.log(newObj)
console.log(obj)
</script>
</body>
</html>
效果展示:
二、深拷贝
深拷贝:拷贝多层,不再拷贝地址
实现深拷贝三种方式?
(1)利用JSON序列化(常用)
(2)利用js库 lodash里面的 _.cloneDeep() (常用)
(3)自己利用递归函数书写深拷贝(理解)
在进行深拷贝时,会拷贝所有的属性,并且如果这些属性是对象,也会对这些对象进行深拷贝,直到最底层的基本数据类型为止。这意味着,对于深拷贝后的对象,即使原对象的属性值发生了变化,深拷贝后的对象的属性值也不会受到影响。在开发中,一般如果我想要使用这个对象内的数据,但是不想修改原本的对象内的数据内容时,使用深浅拷贝来复制数据,并对新的对象内的数据进行操作。
2.1 通过 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>深拷贝-JSON序列化</title>
</head>
<body>
<script>
// 深拷贝实现方式一:JSON序列化(常用的方式)
// const obj = {
// name: '佩奇',
// family: {
// father: '猪爸爸'
// },
// hobby: ['跳泥坑', '唱歌']
// }
// // console.log(JSON.stringify(obj))
// // console.log(JSON.parse(JSON.stringify(obj)))
// const newObj = JSON.parse(JSON.stringify(obj))
// console.log(newObj === obj) // false
// newObj.family.father = 'dad'
// console.log(obj)
// console.log(newObj)
// 注意事项:JSON.stringify序列化的时候会忽略 function undefined
const obj = {
name: '佩奇',
love: undefined,
family: {
father: '猪爸爸'
},
hobby: ['跳泥坑', '唱歌'],
sayHi() {
console.log('我会唱歌')
}
}
const newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj)
</script>
</body>
</html>
2.2 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>深拷贝-lodash库实现</title>
</head>
<body>
<!-- 引入lodash库 -->
<script src="./js/lodash.min.js"></script>
<script>
const obj = {
name: '佩奇',
love: undefined,
family: {
father: '猪爸爸'
},
hobby: ['跳泥坑', '唱歌'],
sayHi() {
console.log('我会唱歌')
}
}
// lodash 库实现
const newObj = _.cloneDeep(obj)
// console.log(newObj)
newObj.family.father = 'dad'
console.log(obj)
console.log(newObj)
</script>
</body>
</html>
2.3 通过递归实现
<!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>深拷贝-递归实现深拷贝</title>
</head>
<body>
<script>
// 递归实现深拷贝 - 简版实现对象和数组的拷贝
const obj = {
name: '佩奇',
family: {
father: '猪爸爸'
},
hobby: ['跳泥坑', '唱歌'],
}
// 封装深拷贝函数 cloneDeep()
function cloneDeep(oldObj) {
// 先判断拷贝的是数组还是对象
const newObj = Array.isArray(oldObj) ? [] : {}
// 遍历拷贝属性和值
for (let k in oldObj) {
// console.log(k) // k 是属性
// console.log(oldObj[k]) // oldObj[k] 是属性值
// 把旧对象的值给新对象的属性
if (typeof oldObj[k] === 'object') {
// 如果属性值是引用数据类型,则需要递归再次拷贝
newObj[k] = cloneDeep(oldObj[k])
} else {
// 否则属性值是基本数据类型,则直接赋值即可
newObj[k] = oldObj[k]
}
}
// 返回新对象
return newObj
}
const newObj = cloneDeep(obj)
newObj.family.father = 'dad'
console.log(newObj)
console.log(obj)
</script>
</body>
</html>
三、异常处理
3.1 throw 抛异常
异常处理是指预估代码执行过程中可能发生的错误,然后最大程度的避免错误的发生导致整个程序无法继续运行
总结:
1. throw 抛出异常信息,程序也会终止执行
2. throw 后面跟的是错误提示信息
3. Error 对象配合 throw 使用,能够设置更详细的错误信息
代码分享:
<!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>异常处理-throw抛出异常</title>
</head>
<body>
<script>
// 异常处理 - throw抛出异常
function count(x, y) {
if (!x || !y) {
// throw '请输入参数'
throw new Error('函数的参数不能为空')
console.log(111)
}
return x + y
}
count()
</script>
</body>
</html>
效果展示:
3.2 try /catch 捕获异常
我们想要测试某些代码是否有异常,可以通过try / catch 捕获错误信息(浏览器提供的错误信息) try 试试 catch 拦住 finally 最后
说明: 1. 将预估可能发生错误的代码写在 try 代码段中 2. 如果 try 代码段中出现错误后,会执行 catch 代码段,并截获到错误信息 3. finally 不管是否有错误,都会执行
代码分享:
<!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>try/catch 捕获错误信息</title>
</head>
<body>
<p>我是测试文字</p>
<script>
// try/catch 捕获错误信息
try {
// 要写测试的代码可能出现错误的代码
const p = document.querySelector('.p')
p.style.color = 'red'
} catch (error) {
// 如果try里面的代码出现错误,则进入catch , 参数 error 是错误信息
// console.log(error)
throw error
} finally {
// 不管代码是否有错误都会执行
console.log('不管代码是否有错误都会执行')
}
</script>
</body>
</html>
效果展示:
3.3 debugger
debugger 语句调用调试功能,例如设置断点
代码分享:
<!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>异常处理-debugger</title>
</head>
<body>
<script>
// 异常处理 -debugger
const obj = {
name: '佩奇',
family: {
father: '猪爸爸'
},
hobby: ['跳泥坑', '唱歌'],
}
// 封装深拷贝函数 cloneDeep()
function cloneDeep(oldObj) {
const newObj = Array.isArray(oldObj) ? [] : {}
debugger9
for (let k in oldObj) {
if (typeof oldObj[k] === 'object') {
newObj[k] = cloneDeep(oldObj[k])
} else {
newObj[k] = oldObj[k]
}
}
return newObj
}
const newObj = cloneDeep(obj)
newObj.family.father = 'dad'
console.log(newObj)
console.log(obj)
</script>
</body>
</html>
效果展示: