浅拷贝
所谓浅拷贝,则其拷贝的就是数据,就比如b对象拷贝a对象,a的数据发送变化,其本质其实就是一个赋值的操作,新对象的这些属性数据就会跟旧对象公用一份,也就是说这两个对象指向同一份数据,他们指向同一份内存空间,一个改变就会都改变。
代码演示:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
</body>
<script>
let person = {
uname: '张三',
age: 22,
sex: '男',
arr: ['张三', '李四', '王五'],
obj: {
index: 1,
name: '赵六',
st :{
a : '1'
}
},
}
let demo = {...person}
console.log(demo)
console.log(person)
person.arr.push('小王')
console.log(demo)
console.log(person)
</script>
</html>
深拷贝
深拷贝是指拷贝对象的具体内容,二内存地址是自主分配的,拷贝结束之后俩个对象虽然存的值是一样的,但是内存地址不一样,即他们两个的数据存储空间地址不一样,俩个对象页互相不影响,互不干涉
代码演示:
第一种 :JSON.parse 和 JSON.stringify搭配(有弊端,函数会被过滤)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>深拷贝</title>
</head>
<body>
</body>
<script>
// 弊端 : 无法复制函数,且函数会被过滤掉
var a={x:1 , y : [a = 1, b = {c : 2} ] , get(){}}
var b=JSON.parse(JSON.stringify(a))
console.log(a,'a')
console.log(b,'b')
a.x=2
console.log(a,'a')
console.log(b,'b')
</script>
</html>
原理 : JSON.stringify将数据转换成JSON数据对象,JSON.parse再将JSON数据对象转换成js数据类型对象,并且会自己去构建新的内存地址存放数据
第二种 : jQuery 封装的方法($.extend()) , 必须先引入jquery
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>深拷贝</title>
</head>
<body>
</body>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
let person = {
uname: '张三',
arr: ['李四', '王五'],
obj: {
index: 1,
},
say: function () {
console.log('hello javascript')
}
}
let son = {}
// 第一个参数必须是 true
$.extend(true, son, person) // 通过 $.extend() 方法实现深拷贝
console.log(son,'son')
console.log(person,'person')
person.uname = '李四'
console.log(son,'son')
console.log(person,'person')
</script>
</html>
第三种 : 使用Object.assign() (存在弊端,只能嵌套浅层,多层就会出现浅拷贝的情况)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>深拷贝</title>
</head>
<body>
</body>
<script src="http://code.jquery.com/jquery-latest.js"></script> <!-- 在线引入jquery -->
<script>
//第三种 : 使用Object.assign() (存在弊端,只能嵌套单层 , 第二层开始就会出现浅拷贝的情况)
var person = { name : '张三' ,age : 100, hobby : ['篮球' ,'rap' ,'唱跳'] }
var son = Object.assign({} , person)
console.log(person, 'person');
console.log(son, 'son');
person.hobby.splice(2 , 1)
console.log(person, 'person');
console.log(son, 'son');
</script>
</html>
第四种 : 使用递归来实现深拷贝
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>深拷贝</title>
</head>
<body>
</body>
<script>
// 第四种 : 使用递归
let person = {
uname: '张三',
arr: ['小明'],
obj: {
index: 1,
},
say: function () {
console.log('hello javascript')
}
}
let son = {}
function myCopy(newObj, obj) {
for(let key in obj) {
if (obj[key] instanceof Array) {
newObj[key] = []
myCopy(newObj[key], obj[key])
} else if (obj[key] instanceof Object) {
newObj[key] = {}
myCopy(newObj[key], obj[key])
} else {
newObj[key] = obj[key]
}
}
}
// 调用递归函数
myCopy(son, person)
person.arr.push('小王')
console.log(person,'person')
console.log(son,'son')
</script>
</html>
但这种方法似乎也有些问题,大家可以观察到进行拷贝后,函数的类型发生了改变,这里我感觉可能是因为函数是特殊的对象导致的,这里希望有大佬可以评论或者私信告知