JS常用的深、浅拷贝

617 阅读2分钟

在JS中,数据类型分为基本数据类型和引用数据类型两种。对于基本数据类型来说,它的值直接存储在栈内存中,而对于引用类型来说,它在栈内存中只是存储了一个指向对内存的引用,而真正的数据存储在堆内存中。

object、array 这两个就是引用类型,当我门直接去拷贝的话(copyObj = obj), 拷贝的是指obj的引用,当你修改copyObj时候,obj也会同时改变;数组也一样道理。

深拷贝

所谓的深拷贝,要实现的效果是不管对象或数组里面嵌套了多少层引用类型,都能拷贝出来,而非只拷贝它的引用

要实现深拷贝的方法常用有一下方法:

1、JSON.parse、JSON.stringify

let obj2 = JSON.parse(JSON.stringify(obj1))

缺点:undefined、function、symbol 会在转换过程中被忽略

2、递归深拷贝

// 不支持循环引用
function deepCopy (src) {
    if (!src || typeof src !== 'object') return src // 判断是否为array || object
    let temp = Array.isArray(src) ? [] : {}
    for (let key in src) {
        if (src.hasOwnProperty(key)) { // 过滤继承来的属性
            if (src[key] && typeof src[key] === 'object') { // 若属性也是引用类型
                temp[key] = deepCopy(src[key]) // 递归克隆
            } else {
                temp[key] = src[key] // 非引用类型就直接拷贝
            }
        }
    }
    return temp
}

let obj2 = deepCopy(obj1)

浅拷贝

那么浅拷贝,简单引用类型直接赋值

或者引用类型的首层进行了深拷贝,但是属性中还有引用类型,只是拷贝它的引用,这样的情况下,也为浅拷贝

以下浅拷贝方法,都只是实现了首层的深拷贝,当嵌套引用类型就要只会拷贝它的引用

1、ES6扩展运算符

let obj2 = {...obj1} // 对象浅拷贝
let arr2 = [...arr1] // 数组浅拷贝

2、Object.assign()

let obj2 = Object.assign({}, obj1)

3、遍历

let shallowCopy = obj => {
  let temp = {}
  //  遍历对象
  for (let key in obj) {
    // 只复制本身拥有的属性(非继承过来的属性)枚举属性
    if (obj.hasOwnProperty(key)) {
      temp[key] = obj[key]
    }
  }
  return temp
}
let obj2 = shallowCopy(obj1)

3、concat()

let arr2 = [].concat(arr1)

相关链接:

JS的防抖、节流函数

八步开发一个vue的组件库

VUE的实现原理(数据劫持、观察者模式)

Javascript实现简单的冒泡排序、插入排序

一个非常简单的-发布订阅模式