如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。
此篇文章中也会简单阐述到栈堆基本数据类型引用数据类型,因为这些概念能更好的让你理解深拷贝与浅拷贝。

你的凯哥呀

举个栗子,有时候开发中会遇到一下情况:

let a = [1,2,3,4,5]
let b = a
console.log(a === b) // true 因为栈内存a、栈内存b访问的同一块堆内存

// 那么问题来了

a[0] = '我变了昂'
console.log(b) // ['我变了昂',2,3,4,5]  怎么肥事

面试常问,基本数据类型有哪些,number,string,boolean,null,undefined五类。

引用数据类型(Object类)有常规名值对的无序对象{a:1},数组[1,2,3],以及函数等。

基本数据类型与引用数据类型的区别

基本数据类型

例如 let a = 1

栈内存
nameval
a1

当你b=a复制时,栈内存会新开辟一个内存,例如这样:

栈内存
nameval
a1
b1

所以当你此时修改a=2,对b并不会造成影响,因为此时的b有独立的内存空间了,不受a的影响了。当然,let a=1,b=a;虽然b不受a影响,但这也算不上深拷贝,因为深拷贝本身只针对较为复杂的object类型数据。

引用数据类型

引用数据类型–名存在栈内存中,值存在于堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值,我们以上面浅拷贝的例子画个图:

堆内存
val
1
1

其实上图表示b=a 其实是将b的堆内存指向与a相同的内存

实现深拷贝的三种方法

1.根据数据类型封装一个方法

function deepClone(obj) {
  let newobj = obj instanceof Array ? [] : {} // 或者 Array.isArray(obj)?[]: {}
  // 上边的方法是判断obj的数据类型  是对象还是数组
  if (typeof obj !== 'obj') {
    return obj
    // 判断是不是基本数据类型,如果是直接返回
  } else {
    // 数组、类数组、对象
    for(var key in obj) {
      newobj[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
      // 判断obj[key]是不是数组或者对象,如果是则传进deepClone,否则直接返回
    }
  }
  return newobj
}

2.使用JSON的stringify()、parse()

const deepClone = (obj) => {
  return JSON.parse(JSON.stringify(obj))
}

3.使用JQ的$.extends

$.extend( [deep ], target, object1 [, objectN ] )

deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝

target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。

object1  objectN可选。 Object类型 第一个以及第N个被合并的对象。 

let a=[0,1,[2,3],4],
    b=$.extend(true,[],a);
a[0]=1;
a[2][0]=1;
console.log(a,b);

发表回复

您的电子邮箱地址不会被公开。