JS数组深拷贝、对象深拷贝

386 阅读2分钟

为什么要进行深拷贝?

这是由于js定义的基础数据类型和复杂数据类型的本质决定的,基础数据类型存储在堆中,拷贝赋值引用的是值,修改拷贝后的值并不会影响原值;复杂数据类型值存储在堆中,引用地址存储在栈中,拷贝赋值的是引用地址,修改拷贝后的值会影响原值。
有时候需要对拷贝的值进行修改,但是又不想影响原来的值,便需要深拷贝。
对象是引用类型。

具体实现

数组的深拷贝
  1. 利用for循环+push
let arr = [1,2,3,4,5]
let resArr = []
for(let i = 0; i <= arr.length-1; i++) {
    resArr.push(arr[i])
}
console.log(resArr) //[1,2,3,4,5]
  1. 利用slice截取特定范围内容不会影响原数据的方法
slice()方法:①slice()数组和字符串都可用;②arr/str.slice(start[包括],end[不包括]),例如对于上方数组里的arr,执行arr.slice(1,3),从左往右开始第一个元素到第三个元素,截取的是[2,3];③省略end表示截取到末尾;④负数代表从右往左数
let arr = [1,2,3,4]
let resArr = arr.slice(0)
console.log(resArr) //[1,2,3,4]
  1. 利用concat合并空数组得到一个新数组
let arr = [1,2,3,4]
let resArr = arr.concat()
console.log(resArr) //[1,2,3,4]
  1. 利用ES6拓展运算符...展开得到一个新数组
let arr = [1,2,3,4]
let resArr = [...arr]
console.log(resArr) // [1,2,3,4]
  1. JOSN.parse(JSON.stringify(arr))
对象的深拷贝
  1. JSON.parse(JSON.stringfy())
    notice:对象中有function,不能正确深拷贝
let obj = {name: '小明', age: 18}
let newObj = JSON.parse(JSON.stringfy(obj))
  1. 利用ES6对象的Object.assign()方法
    notice:只能针对对象属性为基本类型的情况
let obj = {name: '小明', age: 18}
let obj2 = Object.assign({}, obj)

上面的方法,只能克隆拷贝对象本身的值,而不能克隆继承的值,如果需要保持继承,使用下面方法

let obj = {name: '小明', age: 18}
function cloneObj(originObj) {
    let originObjProto = Object.getPrototypeOf(originObj);
    return Object.assign(Object.create(originObjProto), originObj)
}
let newObj = cloneObj(obj)
  1. 利用for循环遍历对象,并判断子属性仍旧为对象时递归,需要时调用,完美克隆对象中的function
function cloneObj(obj) {
    if(typeof obj !== 'object') {
        return obj;
    }else {
        let newobj = obj.constructor === Array ? [] : {};
        for(let i in obj) {
            newobj[i] = typeof obj[i] === 'object' ? cloneObj(obj[i]) : obj[i];
        }
        return newobj
    }
}
cloneObj(需要深拷贝的obj)
/**
 * 数组对象深拷贝
 * @param obj
 * @returns {*}
 */
export default function cloneObj(obj) {
  let str = null
  let newobj = obj.constructor === Array ? [] : {}
  if (typeof obj !== 'object') {
    return
  } else if (window && window.JSON) {
    str = JSON.stringify(obj) // 系列化对象
    newobj = JSON.parse(str) // 还原
  } else {
    for (var i in obj) {
      newobj[i] = typeof obj[i] === 'object' ? cloneObj(obj[i]) : obj[i]
    }
  }
  return newobj
}

对象的浅拷贝

const info = {name: "why", age: 18};
const obj = Object.assign({}, info);
info.name = "kobe";