12. js中的深浅拷贝
在js中,一般使用栈内存保存基础数据类型,和引用类型地址(存取速度慢,存放量大,其引用指针存于栈区,并指向引用本身),而堆内存则存储引用数据类型。
赋值
将某一数值或某一对象赋值给变量的过程
基础数据类型:赋的是值,赋值后两个变量不相互影响
jsvar a = 100 var b = a a = 200 console.log(a,b) // 200, 100
引用数据类型: 赋的是地址,两个变量具有相同的引用,指向同一个对象,相互之间会影响
js
var a = {c: 1000};
var b = a
a.c = 2000
console.log(a.c, b.c) // 2000, 2000 全部是2000,a,b指向同一份数据
浅拷贝
浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
Object.assign
将多个源对象中所有可枚举的自有属性复制到目标对象,并返回修改后的目标对象
js
let obj1 = {
person: {
name: 'likewei',
age: 25
},
sports: 'basketball'
}
let obj2 = Object.assign({}, obj1)
obj2.person.name = 'testhaha'
obj2.sports = 'football'
console.log(obj1)
/** {
person: {
name: 'testhaha',
age: 25
},
sports: 'basketball'
} */
loadsh的_.clone方法
js
var _ = require('loadsh')
var obj1 = {
a:1,
b: {f: {g: 1}},
c: [1, 2, 3]
}
var obj2 = _.clone(obj1)
console.log(obj1.b.f == obj2.b.f) // true
展开运算符(...)
js
let obj1 = {name: 'likewei', address: {x: 1, y: 2}}
let obj2 = {...obj1}
obj1.address.x = 200
obj1.name= 'kobe'
console.log('obj2', obj2) // {name: 'likewei', address: {x: 200, y: 2}}
Array.prototype.concat
js
let arr = [1, 3, {username: 'likewei'}]
let arr2 = arr.concat()
arr2[2].username = 'testhaha'
console.log(arr[2].username) // 'likewei'
Array.prototype.slice
js
let arr = [1, 3, {
username: ' kobe'
}];
let arr2 = arr.slice()
arr2[2].username = 'likewei'
console.log(arr) // [1, 3, {username: 'likewei'}]
深拷贝
从堆内存中开辟一个新的区域存放新对象,对对象中的子对象进行递归拷贝,拷贝前后的两个对象互不影响。
JSON.parse(JSON.stringify())
js
let obj1 = {name: 'likewei', address: {x: 100, y: 100}}
let obj2 = JSON.parse(JSON.stringify(obj1))
obj2.address.x = 100
console.log(obj1) // {name: 'likewei', address: {x: 100, y: 100}}
loadsh的_.clonedeep方法
js
var _ = require('lodash');
var obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);// false
手写递归
遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝。
js
// 丐版
function cloneDeep(obj, map = new WeakMap()) {
if(typeof obj == 'object') {
let target = Array.is(obj) ? [] : {}
if(map.get(obj)) {
return map.get(obj)
}
map.set(obj, target)
for(const i in obj) {
target[i] = cloneDeep(obj[i], map)
}
return target
} else {
return obj
}
}