一、基本类型和引用类型
基本类型:string,number,boolean,null,undefiend,symbol
引用类型:Function,Array,Object
1、基本数据类型的特点:直接存储在栈(stack)中的数据
2、引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里
二、浅拷贝和深拷贝
1、浅拷贝、深拷贝的概念
- 浅拷贝就是创建一个新对象,这个对象对原始对象进行了精确拷贝。
若属性是基本类型,拷贝的就是属性的值;
若属性是引用类型,拷贝的就是内存地址,
若其中一个对象改变了这个地址,就会影响到另一个对象。 - 深拷贝就是将一个对象完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,修改新对象不会影响到原对象。
2、赋值、浅拷贝、深拷贝区别
浅拷贝、深拷贝主要都是针对object或者array数据类型的,所以比较的前提是针对引用类型。
- 当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。
- 深拷贝:重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,但拷贝前后对象的引用类型因共享同一块内存,会相互影响。
- 从堆内存中开辟一个新的区域存放新对象,对对象中的子对象进行递归拷贝,拷贝前后的两个对象互不影响。
三、浅拷贝实现方式
1. Object.assign()
Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。
var obj = { a: {a: "kobe", b: 39} };
var initalObj = Object.assign({}, obj);
initalObj.a.a = "wade";
console.log(obj.a.a); // wade
// 注意:当object只有一层的时候,是深拷贝
let obj = {
username: 'kobe'
};
let obj2 = Object.assign({},obj);
obj2.username = 'wade';
console.log(obj);//{username: "kobe"}
- Array.prototype.concat() 修改新对象会改到原对象
- Array.prototype.slice()
四、深拷贝实现方式
- JSON.parse(JSON.stringify())
- 手写递归方法
- 函数库lodash
五、手写函数实现深拷贝和浅拷贝
// 手写实现深拷贝和浅拷贝之浅拷贝:
let shallowObj01 = {
name: "小王",
age: "18",
hobbit: ["唱歌", "跳舞", "吃火锅"],
};
let shallowObj02 = shallowClone(shallowObj01);
shallowObj02["name"] = "大王";
shallowObj02["age"] = "28";
shallowObj02["hobbit"].push("打游戏");
function shallowClone(obj) {
let target = {};
for (let i in obj) {
// eslint-disable-next-line no-prototype-builtins
if (obj.hasOwnProperty(i)) {
target[i] = obj[i];
}
}
return target;
}
console.log("shallowObj01", shallowObj01);
console.log("shallowObj02", shallowObj02);
// 手写实现深拷贝和浅拷贝之深拷贝:
let deepObj01 = {
name: "cat",
age: "2",
hobbit: ["sing", "dance"],
};
let deepObj02 = deepClone(deepObj01);
deepObj02["name"] = "布丁";
deepObj02["age"] = "5";
deepObj02.hobbit.push("eat ice cream");
function deepClone(obj) {
if (obj === null) return obj;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
if (typeof obj !== "object") return obj;
let cloneObj = new obj.constructor();
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
cloneObj[i] = deepClone(obj[i]);
}
}
return cloneObj;
}
console.log("deepObj01", deepObj01);
console.log("deepObj02", deepObj02);