1、浅拷贝
定义: 把对象拷贝给一个新对象,开发中我们经常需要复制一个对象。可以直接拷贝一个新的对象,如果直接赋值,则复制的是地址,修改任何一个对象,另一个对象都会改变。
常见方法:
1、拷贝对象:
Object.assign()
展开运算符{...obj
2、拷贝数组:
Array.prototype.concat()
展开运算符 [...arr
代码如下:
const Obj = {
name: '张三'
}
// Object.assign({},对象) 对象拷贝的方法
const newObj = Object.assign({},Obj)
// 展开运算符的拷贝方法
// const newObj = {...Obj}
newObj.name = '李四'
console.log(Obj)
console.log(newObj)
const arr = ['张三']
// [].concat(数组) 数组拷贝的方法
// const newArr = [].concat(arr)
// 展开运算符的拷贝方法
const newArr = [...arr]
newArr[0] = '李四'
console.log(arr)
console.log(newArr)
总结:对象和数组的浅拷贝就是把对象里面的属性和值复制一份,放到新对象中存储,新老对象是不同的地址值,所以修改其中一个对象,不会影响另一个对象的属性。
浅拷贝注意点:
1、如果是基本数据类型拷贝值
2、如果是引用数据类型拷贝的是地址
简单理解:如果是单侧对象,没有问题,如果有多层就有问题,还是会影响原来对象,浅拷贝就是只开被对象第一层的数据,如果对象都是基本数据类型则没有任何问题,只要有引用数据类型的属性,就会将其地址值复制一份,导致两个对象的属性共用同一个对象。
2、深拷贝
深拷贝:拷贝多层,不再拷贝地址
常见方法:
1、通过 JSON 序列化实现
利用 JSON 的序列化和反序列化机制,取巧的方案,非常简单好用。
序列化:将对象转成字符串 JSON.stringify()
反序列化:将字符串转成对象 JSON.parse(
演示代码:
const obj = {
name: '张三',
hoppy: ['吃饭','睡觉'],
family: {
father: '张四'
}
}
// 利用 JSON 的序列化和反序列化机制
// 1. 将对象转换为字符串
const str = JSON.stringify(obj)
// 2. 将字符串再转换为一个新的对象
const OBJ = JSON.parse(str)
// 这样就能实现深拷贝,对新对象进行修改不会影响旧对象
注意事项 :使用 JSON.stringify() 和 JSON.parse() 进行深拷贝,无法拷贝 undefined 和 function。
2、lodash库 实现
js库 lodash里面 _.cloneDeep 内部实现了深拷贝
官网地址:Lodash 简介 | Lodash 中文文档 | Lodash 中文网
参数:需要深拷贝的对象
返回值:拷贝好的新对象
连同 undefined 和 function 和函数一并拷贝进来
对比第一种方法的优缺点:
优点:相较于序列化和反序列化的优势是更完善
缺点:需要额外引用一个第三方的 js 文件,增加项目体积
<!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>
<script src="./lodash.min.js"></script>
</head>
<body>
<script>
const obj = {
name: '张三',
hoppy: ['吃饭','睡觉'],
family: {
father: '张四'
}
age: undefined,
gender:function(){}
}
// 这样就可以对newObj进行修改和获取函数和undefined的内容了
const newObj = _.cloneDeep(obj)
newObj.name = '李四'
console.log(obj)
console.log(newObj)
</script>
</body>
</html>
3、通过递归实现
定义:所谓递归就是一种函数调用自身的操作
1、简单理解:函数内部自己调用自己, 就是递归,这个函数就是递归函数
2、递归函数的作用和循环效果类似
3、由于递归很容易发生“栈溢出”错误(stack overflow),所以记得添加退出条件 return
实现代码:
var obj= {
"name":"张三",
"age":22,
"job":"程序员",
"height":175,
"type":{
"character":"tender"
}
}
obj.__proto__.say=function(){ }
function deepCopy(obj){
var copyObj={ };
for(var key in obj){
if(obj.hasOwnProperty(key) == true){
if(obj[key] instanceof Object){
copyObj[key] = deepCopy(obj[key])
}else{
copyObj[key] = obj[key]
}
}
}
return copyObj;
}
var obj2 = deepCopy(obj)
console.log(obj2)
实现思路:首先创建一个新对象,循环赋值,如果对象的属性值是对象,创建新对象,循环赋值。