在日常开发及面试过程中,总是可以涉及到数据的拷贝。浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。深拷贝是新开辟一个新的地址空间,新旧对象不共享内存,修改新对象不会改变原对象。 本期内容带你深入了解javascript 的拷贝。
基础知识
在理解 深拷贝 和 浅拷贝之前 ,我们先了解下JavaScript有哪些类型:
- 基本数据类型 : Number、String、Boolean、undefined、Null、以及Es6新特性Symbol、或者Es10中的Bigint( BigInt是一种新的数据类型,用于当整数值大于Number数据类型支持的范围时。这种数据类型允许我们安全地对
大整数执行算术操作,表示高分辨率的时间戳,使用大整数id,等等,而不需要使用库。Bigint )。 - 引用数据类型: 对象Object(包含普通对象-Object,数组对象-Array,正则对象-RegExp,日期对象-Date,数学函数-Math,函数对象-Function)。
浅拷贝 和 深拷贝 ?
浅拷贝:拷贝的是引用地址,如果地址内的内容发生改变,所有的内容也会相应的改变。
// 赋值拷贝
let obj = {a:1};
let obj1 = obj;
obj1.a = 2;
console.log(obj); // {a:2}
// 循环拷贝
let obj = {
name:'a',
age:18,
fruit:{
apply:5
}
}
let obj2 = {};
for(let key in obj){
obj2[key] = obj[key];
}
obj2.name = 'b';
obj2.fruit.apply = 8;
console.log(obj); // {name: 'a', age: 18, fruit: {apply: 8}}
console.log(obj2); // {name: 'b', age: 18, fruit: {apply: 8}}
// Object.assign()
let obj = {
name:'a',
age:18,
fruit:{
apply:5
}
}
let obj3 = Object.assign({}, obj);
obj3.name = 'd';
obj3.fruit.apply = 8;
console.log(obj); // {name: 'a', age: 18, fruit: {apply: 8}}
console.log(obj3); // {name: 'd', age: 18, fruit: {apply: 8}}
// 拓展运算符
let obj = {
name:'a',
age:18,
fruit:{
apply:5
}
}
let obj4 = {...obj};
obj4.name = 'e';
obj4.fruit.apply = 8;
console.log(obj); // {name: 'a', age: 18, fruit: {apply: 8}}
console.log(obj4); // {name: 'e', age: 18, fruit: {apply: 8}}
深拷贝:拷贝的是对象或者数组内部数据的属性值,在堆中开辟属于自己的内存区域。
// JSON.parse(JSON.stringify());
let obj = {
name:'a',
age:18,
fruit:{
apply:5
}
}
let newobj = JSON.parse(JSON.stringify(obj));
newobj.fruit.apply = 8;
console.log(obj); // {name: 'a', age: 18, fruit: {apply: 5}}
console.log(newobj); // {name: 'a', age: 18, fruit: {apply: 8}}
JSON 只支持object、array 、string、number、true、false、null 这几种数据或者值,其他的比如函数,undefined、Date、RegExp 等数据类型都不支持,对于它不支持的数据都会直接忽略该属性。
- 函数
let obj = {
name:'a',
age:18,
fruit:{
apply:5
},
b:[1,2,3],
c:function(){
console.log('我是函数');
}
}
let newobj = JSON.parse(JSON.stringify(obj));
console.log(newobj);
// { "name": "a", "age": 18, "fruit": {"apply": 5},"b": [1,2,3]}
- undefined
let obj = {
a:undefined
}
let newobj = JSON.parse(JSON.stringify(obj));
console.log(newobj); // {}
- RegExp
let obj = {
a:/[0-9]+/
}
let newobj = JSON.parse(JSON.stringify(obj));
console.log(newobj); // {"a": {}}
- Date
let obj = {
a:new Date()
}
let newobj = JSON.parse(JSON.stringify(obj));
console.log(newobj); // {"a": "2022-07-29T08:52:12.633Z"}
console.log(newobj.getTime()) // newobj.getTime is not a function
- 环状结构的对象 (环就是对象循环引用,导致自己成为一个闭环)
let obj = {name:'a'};
obj.age = obj;
let newobj = JSON.parse(JSON.stringify(obj));
console.log(newobj); // Converting circular structure to JSON --> starting at object with constructor 'Object' --- property 'age' closes the circle at JSON.stringify
// 递归
let obj = {
name:'a',
age:18,
fruit:{
apply:5
}
}
function deepClone(obj) {
var target = {};
for(var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
if (typeof obj[key] === 'object') {
target[key] = deepClone(obj[key]);
} else {
target[key] = obj[key];
}
}
}
return target;
}
let newobj= deepClone(obj);
newobj.fruit.apply = 8;
console.log(obj); // {name: 'a', age: 18, fruit: {apply: 5}}
console.log(newobj); // {name: 'a', age: 18, fruit: {apply: 8}}
后记
以上就是本期 拷贝 相关的内容,希望对小伙伴们更好的掌握这方面的知识点有些许帮助,不要忘了来个点赞哦 👍 ~~。有任何问题还望各位大佬批评指正,谢谢!后续持续更新。。。