资讯专栏INFORMATION COLUMN

实现JS中的浅拷贝和深拷贝

huangjinnan / 1914人阅读

摘要:浅拷贝和浅拷贝的问题,不仅在日常应用中需要注意,而且在面试和笔试中也常被用来考察应聘者,属于文体两开花的。基本数据类型引用数据类型等等基本数据类型是按值访问的,对其的拷贝会直接复制其值保存在新变量中。方法手工遍历法方法方法方法方法

浅拷贝浅拷贝的问题,不仅在日常应用中需要注意,而且在面试和笔试中也常被用来考察应聘者,属于“文体两开花”的points。

什么是深拷贝和浅拷贝呢?
名称 定义
浅拷贝 对基本数据类型进行值传递,对引用数据类型进行引用传递形式的拷贝
深拷贝 对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容

也就是说,对于a,让b对a进行拷贝,之后当a发生变化,若b也跟着发生变化,就是浅拷贝;若a发生变化,b不变化,那就是深拷贝。

基本数据类型 引用数据类型
Number、String、Boolean、Null、Undefined等 Object、Array、Function等

基本数据类型是按值访问的,对其的拷贝会直接复制其值保存在新变量中。例如Number类型:

var a = 1;
b = a;
console.log(b); // 1
a = 2;
console.log(b);  //1 (a的变化不会影响b的值)

而“引用数据类型”是按引用访问的,对其直接进行拷贝只会操作引用地址,而不是值本身。例如Array类型:

var a = [1, 2, 3];
b = a;
console.log(a);  // [1, 2, 3]
console.log(b);  // [1, 2, 3]
a[0] = 2;
console.log(a);  // [2, 2, 3]
console.log(b);  // [2, 2, 3]  (对数组a的改动也影响了数组b)

其原理如下图所示:

那么,如何对引用数据类型实现深拷贝呢?

显而易见的思路是:既然是因为引用地址造成了无法深拷贝,那就抛开引用地址,直接对值进行遍历,将其拷贝给新的变量。
方法1: 手工遍历法
let a = [1, [2, 3], 4];
const copy = (obj) => {
  let newObj = obj.constructor === Array ? [] : {}
  if(typeof obj !== "object") {
    return;
  }
  for(let i in obj) {
    newObj[i] = typeof obj[i] === "object" ? copy(obj[i]) : obj[i]
  }
  return newObj
}

let b = copy(a);  
a[1][0] = 3;
console.log(a);  // [1, [3, 3], 4]
console.log(b);  // [1, [2, 3], 4]
方法2: JSON方法
let a = [1, [2, 3], 4];

const copy = (obj) => {
  let _obj = JSON.stringify(obj)
  let newObj = JSON.parse(_obj)
  return newObj
}

let b = copy(a);  
a[1][0] = 3;
console.log(a);  // [1, [3, 3], 4]
console.log(b);  // [1, [2, 3], 4]
方法3: JQuery-extend方法
let a = [1, [2, 3], 4];

b = $.extend(true,[],a);

a[1][0] = 3;
console.log(a);  // [1, [3, 3], 4]
console.log(b);  // [1, [2, 3], 4]

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/109212.html

相关文章

  • JavaScript的浅拷贝和深拷贝

    摘要:在中可以通过添加一个参数来实现递归,调用就可以实现一个深拷贝。利用序列化实现一个深拷贝 在JavaScript中,对于Object和Array这类引用类型值,当从一个变量向另一个变量复制引用类型值时,这个值的副本其实是一个指针,两个变量指向同一个堆对象,改变其中一个变量,另一个也会受到影响。 这种拷贝分为两种情况:拷贝引用和拷贝实例,也就是我们说的浅拷贝和深拷贝 浅拷贝(shallow...

    ernest.wang 评论0 收藏0
  • JS的浅拷贝和深拷贝

    摘要:说明外层数组拷贝的是实例说明元素拷贝是引用深拷贝在堆中重新分配内存,并且把源对象所有属性都进行新建拷贝,拷贝后的对象与原来的对象完全隔离,互不影响。中的方法可以实现深拷贝,源码原理也是递归使用浅拷贝。 1.浅拷贝 当把数组或对象简单赋值给其他变量的时候,实际上进行的是浅拷贝,浅拷贝是拷贝引用,只是将拷贝后的引用指向同一个对象实例,彼此间的操作还会互相影响。 分为两种情况:直接拷贝源对象...

    xeblog 评论0 收藏0
  • js的浅拷贝和深拷贝和应用场景

    摘要:而大多数实际项目中,我们想要的结果是两个变量初始值相同互不影响。所以就要使用到拷贝分为深浅两种深浅拷贝的区别浅拷贝只复制一层对象的属性,而深拷贝则递归复制了所有层级。 为什么会用到浅拷贝和深拷贝 首先来看一下如下代码 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...

    MartinDai 评论0 收藏0
  • js的浅拷贝和深拷贝和应用场景

    摘要:而大多数实际项目中,我们想要的结果是两个变量初始值相同互不影响。所以就要使用到拷贝分为深浅两种深浅拷贝的区别浅拷贝只复制一层对象的属性,而深拷贝则递归复制了所有层级。 为什么会用到浅拷贝和深拷贝 首先来看一下如下代码 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...

    nemo 评论0 收藏0
  • js的浅拷贝和深拷贝和应用场景

    摘要:而大多数实际项目中,我们想要的结果是两个变量初始值相同互不影响。所以就要使用到拷贝分为深浅两种深浅拷贝的区别浅拷贝只复制一层对象的属性,而深拷贝则递归复制了所有层级。 为什么会用到浅拷贝和深拷贝 首先来看一下如下代码 let a = b = 2 a = 3 console.log(a) console.log(b) let c = d = [1,2,3] let e = f = {a:...

    lavor 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<