类型 | 和原数据是否指向同一对象 | 第一层数据为基本数据类型 | 原数据中包含子对象 |
---|---|---|---|
赋值 | 是 | 改变会使原数据一同改变 | 改变会使原数据一同改变 |
浅拷贝 | 否 | 改变不会使原数据一同改变 | 改变会使原数据一同改变 |
深拷贝 | 否 | 改变不会使原数据一同改变 | 改变不会使原数据一同改变 |
浅拷贝
数组
- 直接遍历
let arr = [1,2,3,4]
function shallowCopy(arr){
let newArr = [];
for(let ele of arr){
newArr.push(ele)
}
return newArr
}
- Array.slice()
slice方法包含两个参数,start和end,第一个参数确定新数组的起始位置,第二个参数确定结尾位置,使用后返回一个新数组,不改变原始值。如果不传参,则返回一个与原来数组长度一样的新数组。
let arr = [1,2,3,4]
let arr1 = arr.slice()
- Array.concat()
concat方法用于将多个数组合并,Array.concat(arr1, arr2, …, arrN),最终返回一个新值,不影响原值。如果参数为空,可以理解为arr.concat([]),即与空数组合并并返回原值。
let arr = [1,2,3,4]
let arr1 = arr.concat()
对象
- 直接遍历
let obj = {
name: 'jack',
age: 19
}
function copy(obj){
let newObj = {}
for(ele in obj){
newObj[ele] = obj[ele]
}
return newObj
}
- Object.assign
Object.assign用于对象合并,将源对象所有可枚举属性,合并到目标对象中。
let obj = {
name: 'jack',
age: 19
}
let newObj = Object.assign({}, obj)
- 扩展运算符
扩展运算符取出当前对象所有可枚举属性拷贝到新的对象当中。
let obj = {
name: 'jack',
age: 19
}
let newObj = {...obj}
但是以上所有方法均只能实现第一层拷贝,一旦内部有其他引用数据就会发现相应数据一经改变其他数据也会改变
let obj = {
name: 'jack',
age: 19,
friends: [1, [2, 3], 4]
}
let newObj = {...obj}
newObj.friends[1] = [1, 2]
console.log(newObj.friends[1]) // [1, 2]
console.log(obj.friends[1]) // [1,2]
深拷贝
- JSON.parse(JSON.stringify(XXX))
let obj = {
name: 'jack',
age: 19,
friends: [1, [2, 3], 4]
}
let newObj = JSON.parse(JSON.stringify(obj))
newObj.friends[1] = [1, 2]
console.log(newObj.friends[1]) // [1, 2]
console.log(obj.friends[1]) // [2, 3]
- 递归实现深拷贝
let obj = {
name: 'jack',
age: 19,
friends: {
{
name: 'mack',
age: 19,
},
{
name: 'sun',
age: 18,
}
}
}
function deepCopy(value){
let newValue = value.constructor === Object ? {} : [];
if(typeof value !== 'object'){
return;
}
for(let ele in value){
newValue[ele] = typeof value[ele] === 'object' ? deepCopy(value[ele]) : value[ele]
}
return newValue
}
以上代码还有些问题,没考虑对象中的方法和正则等,待添加~
感谢
深拷贝和浅拷贝一直都觉得挺麻烦的,这次详细的读了读几篇文章,清晰多了
js 深拷贝 vs 浅拷贝
【javascript】详解javaScript的深拷贝
感谢原作者!