js 拷贝
- js拷贝有浅拷贝和深拷贝。
-
浅拷贝:只会将原始对象的属性复制到新对象中,如果原始对象包含引用对象属性,那么只会复制其引用。当原始对象引用对象属性改变,拷贝对象的引用属性也会跟着改变。
-
深拷贝:创建一个对象,把原对象的所有属性都拷贝(包括引用类型)。并且无论怎么改变原对象的属性,新对象都不会发生变化
一、浅拷贝(引用对象属性只复制引用)
// 浅拷贝(只能拷贝对象的基本数据类型属性)
// 1、Object.assign (对象使用)
const obj = {
name: '张三',
age: '18'
}
const newObj = Object.assign({}, obj)
console.log(newObj) // { name: '张三', age: '李四' }
// 2、for in 循环 (对象、数组使用)
function shallowCopy(source){
var target = source instanceof Array ? [] : {};
for(var i in source){
// 使用 hasOwnProperty 方法判断属性是否存在
if(source.hasOwnProperty(i)){
target[i]=source[i];
}
}
return target;
}
// 3、Array.prototype.slice() (数组使用)
const arr = [1, 2, 3, 4]
const newArr = arr.slice(0)
console.log(newArr) // (4) [1, 2, 3, 4]
// 4、Array.prototype.concat() (数组使用)
const arr2 = [1, 2, 3, 4]
const newArr2 = arr2.concat(arr2)
console.log(newArr2) // (4) [1, 2, 3, 4]
// 5、Array.concat() (数组使用)
const arr3 = [1, 2, 3, 4]
const newArr3 = Array.from(arr3)
console.log(newArr3) // (4) [1, 2, 3, 4]
二、深拷贝
// 深拷贝
// 1、JSON.parse() 和 JSON.stringify() (对象、数组使用)
/**
JSON.parse() 和 JSON.stringify() 也算深拷贝,但是它不能处理函数、undefined、
Symbol、Date等。对于大型数据结构,JSON.stringify() 和 JSON.parse() 可能非常慢,
因为它们需要遍历整个对象并创建新的数据结构
存在的坑:
· 如果对象中有函数有方法就不能实现拷贝了
· 会抛弃对象的constructor,所有的构造函数会指向Object
· 对象有循环引用,会报错
*/
let objJson = {
name: 'aaa',
age: 30,
action: function () {}
}
const arrJson = [1, 2, 3, 4]
console.log(JSON.parse(JSON.stringify(objJson)))
console.log(JSON.parse(JSON.stringify(arrJson)))
// 2、使用递归
function deepCopy(obj, parent = null) {
// 创建一个新对象
let result = {}
let keys = Object.keys(obj),
key = null,
temp= null,
_parent = parent
// 该字段有父级则需要追溯该字段的父级
while (_parent) {
// 如果该字段引用了它的父级则为循环引用
if (_parent.originalParent === obj) {
// 循环引用直接返回同级的新对象
return _parent.currentParent
}
_parent = _parent.parent
}
for (let i = 0; i < keys.length; i++) {
key = keys[i]
temp= obj[key]
// 如果字段的值也是一个对象
if (temp && typeof temp=== 'object') {
// 递归执行深拷贝 将同级的待拷贝对象与新对象传递给 parent 方便追溯循环引用
result[key] = deepCopy(temp, {
originalParent: obj,
currentParent: result,
parent: parent
});
} else {
result[key] = temp
}
}
return result
}
const obj1 = {
x: 1,
y: 2
}
obj1.z = obj1
var obj2 = deepCopy(obj1)
console.log(obj1) //太长了去浏览器试一下吧~
console.log(obj2) //太长了去浏览器试一下吧~