JS面试高频:浅拷贝、深拷贝
对象的引用
- 对象的变量存储的不是对象本身,而是该对象“在内存中的地址” —— 即该对象的“引用”
- 当一个对象变量被复制 —— 引用被复制,而该对象自身并没有被复制
let user = { name:'John' };
let admin = user;
admin.name = 'Pete'; //通过 "admin" 引用来修改
alert(user.name); //'Pete' ,修改能通过 "user" 引用看到
复制对象:即分为浅拷贝&深拷贝
1.浅拷贝:
—数组或对象中的值是基本类型数据,拷贝后的数据和原数据是完全独立的;
—若数组或对象的值是引用类型数据,拷贝后的数组或对象中的引用类型的值跟原数据中的引用类型的值,共享同一地址
- 创建一个新对象,遍历已有对象的属性,并在原始类型值的层面复制它们
let user = {
name:'John',
age: 30
};
let clone = {}; //新的空对象
// 将 user 中所有的属性拷贝到其中
for (let key in user) {
clone[key] = user[key];
}
//现在 clone 是带有相同内容的完全独立的对象
clone.name = 'Pete';
alert(user.name); //'Johhn'
- 浅拷贝的语法糖(ES6中): Object.assign(dest, [src1, src2, src3…])
其中,dest:目标对象 ; [src1, src2, src3…]:源对象
注:若拷贝的属性已存在,则会被覆盖
let user = { name:'John' };
let permission1 = { canView: true };
let permission2 = { canEdit: true };
// 将 permission1 和 permission2 中的所有属性都拷贝到 user 中
Object.assign(user, permission1, permission2)
//现在 user = { name:'John', canView: true, canEdit: true }
2.深拷贝:
- 不管原数据中值是什么类型的数据,拷贝后的新数据跟原数据是完全独立的
用一个拷贝循环来检查 obj[key] 的每个值,若它是一个对象,则也复制它的结构
- 代码(非常重要!要会默写!)
var obj = {
id:1,
name:'andy',
msg:{
age:18
},
color:['pink','red']
};
var 0 = {};
// 封装函数
function deepCopy(newobj,oldobj) {
for(var key in oldobj) {
//判断属性值属于哪种数据类型
//1.获取属性值 oldobj[key]
var item = oldobj[key];
//2.判断该值是否是数组
//注意:先判断数组,因为数组属于Object,写在对象后面就不会再去判断是否为数组类型
if (item instanceof Array) {
newobj[key] = [];
deepCopy(newobj[key],item);
} else if (item instanceof Object) {
//3.判断该值是否是对象
newobj[key] = {};
deepCopy(newobj[key],item);
} else {
//4.属于简单数据类型
newobj[key]=item;
}
}
}
总结:
浅拷贝:只拷贝一层,更深层次的对象级别只拷贝引用
深拷贝:拷贝多层,每一级别的数据都会拷贝