持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
浅拷贝与深拷贝
-
浅拷贝:可以理解为一个新的对象只是简单的复制了原有对象的内存地址
新旧对象指向的都是同一个引用地址 -
深拷贝:完全开辟出的一个新空间来存放和旧对象中一模一样的数据,两者只是内容一样而已,
改变原有对象,新复制出来的对象不会受到任何影响
浅拷贝
浅拷贝就是通过赋值的方式进行拷贝,那为什么说这是浅拷贝呢?就是因为赋值的方式只会把对象的表层赋值给一个新的对象,如果里面有属性值为数组或者对象,那么就只会拷贝到该属性在栈空间的指针地址,新对象的这些属性数据就会跟旧对象公用一份,也就是说两个地址指向同一份数据,一个改变就会都改变。
let person = {
name:'ly',
hobby:['play','sleep','eat']
}
let newPerson = Object.assign({},person)
newPerson.hobby.push('football')
我们发现我们只是修改了newPerson对象上的hobby,但是person上面的hobby也跟着改变了。
所以,当对象中的属性有引用类型时,有时候使用浅拷贝就不太合适了。那么一般的浅拷贝有哪些呢?
我们发现,使用Object.assign()合并对象,里面的属性是浅拷贝.
let person = {
name:'ly',
hobby:['play','sleep','eat']
}
let person2 = {...person}
person2.hobby.push('swim')
我们发现ES6的扩展运算符也是浅拷贝。
此外,还有直接赋值也是浅拷贝。
let person = {
name:'ly',
hobby:['play','sleep','eat']
}
let person2 = person
person2.hobby.push('swim')
深拷贝
我们发现我们有时候需要的是获得某个对象上面的所有属性,但是修改新对象不会对源对象产生影响,这就需要使用深拷贝了。
当拷贝的目标只有对象
let user = {
name: "ly",
obj: {
height: "170",
age: "18",
},
};
function copy(obj) {
let res = {};
for (const key in obj) {
// 此处用到递归
// 如果循环到对象里面还是对象,就循环里面的对象,层层深入,一直循环到没有对象为止
res[key] = typeof obj[key] === "object" ? copy(obj[key]) : obj[key];
}
return res;
}
let newuser = copy(user);
newuser.obj.age = 19;
当拷贝的目标既有对象也有数组
let person = {
name: "ly",
info: {
age: "18",
height: "170",
},
data: [
{
id: "1",
title: "css",
},
],
};
function copy(obj) {
// 先判断拷贝目标是对象还是数组,用instanceof判断原型是Array还是Object
let res = obj instanceof Array ? [] : {};
for (const [key, value] of Object.entries(obj)) {
res[key] = typeof value === "object" ? copy(value) : value;
}
return res;
}
let newPerson = copy(person);
newPerson.data[0].title = "javascript";
函数也属于对象,它的key就是函数名,value就是函数体。
let person = {
name:'ly',
sayName() {
console.log(this.name)
}
}
for(const [key,value] of Object.entries(person)) {
console.log(key,value)
}
通过 json反序列化实现深拷贝
let person = {
name: 'ly',
age: 18,
hobby: ['eat', 'sleep', 'play'],
obj: {
index: 1,
title: 'css'
},
say: function () {
console.log('hello css')
}
}
function copy(obj) {
let _obj = JSON.stringify(obj)
let newObj = JSON.parse(_obj)
return newObj
}
let son = copy(person)
son.hobby.push('看电视')
但是我们发现这种方式不能拷贝函数,person本来有say函数的,但是通过json反序列化拷贝给son后,我们发现son身上没有了say函数。