我的编程空间,编程开发者的网络收藏夹
学习永远不晚

js深拷贝与浅拷贝一文彻底搞懂

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

js深拷贝与浅拷贝一文彻底搞懂

深拷贝浅拷贝只是针对引用数据类型

JavaScript数据类型包括基本数据类型(Number,String,boolean,Null,Undefined,Symbol)、引用数据类型(Array,Object)

  • 基本数据类型的特点:直接存储在栈(stack)中的数据

  • 引用数据类在栈中存有指针,实体数据存在堆中,通过栈中的指针找到堆中的引用数据类型的实体

浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

赋值和浅拷贝的区别

当我们把一个对象赋值给一个新的变量时,赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。

浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源。

// 对象赋值
var obj1 = {
   'name' : 'zhangsan',
   'age' :  '18',
   'language' : [1,[2,3],[4,5]],
};
var obj2 = obj1;
obj2.name = "lisi";
obj2.language[1] = ["二","三"];
console.log('obj1',obj1)
console.log('obj2',obj2)

image

// 浅拷贝
var obj1 = {
   'name' : 'zhangsan',
   'age' :  '18',
   'language' : [1,[2,3],[4,5]],
};
var obj3 = shallowCopy(obj1);
obj3.name = "lisi";
obj3.language[1] = ["二","三"];
function shallowCopy(class="lazy" data-src) {
   var dst = {};
   for (var prop in class="lazy" data-src) {
       if (class="lazy" data-src.hasOwnProperty(prop)) {
           dst[prop] = class="lazy" data-src[prop];
       }
   }
   return dst;
}
console.log('obj1',obj1)
console.log('obj3',obj3)

image

上面例子中,obj1是原始数据,obj2是赋值操作得到,而obj3浅拷贝得到。我们可以很清晰看到对原始数据的影响,具体请看下表:

image

浅拷贝的实现方法

1. Object.assign()

Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。

对于Object.assign()而言,如果对象的属性值为简单类型(string,number),通过Object.assign({},class="lazy" data-srcobj);得到的新对象为深拷贝;如果属性值为对象或其他引用类型,那对于这个对象而言其实是浅拷贝

2. Array.prototype.concat()

let arr = [1, 3, {
   username: 'kobe'
}];
let arr2=arr.concat();
arr2[2].username = 'wade';
console.log(arr);

image

3. Array.prototype.slice()

let arr = [1, 3, {
   username: ' kobe'
}];
let arr3 = arr.slice();
arr3[2].username = 'wade'
console.log(arr);

image

深拷贝的实现

1. JSON.parse(JSON.stringify())

原理: 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。

这种方法虽然可以实现数组或对象深拷贝,但不能处理函数。

这是因为 JSON.stringify() 方法是将一个JavaScript值(对象或者数组)转换为一个 JSON字符串,不能接受函数

2. 手写递归方法

//递归来实现深拷贝
    function deepClone(obj){
      var newObj = obj instanceof Array ? []:{};
      if(typeof obj !== 'object'){
        return obj;
      }else {
        for(var i in obj) {
          newObj[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i];
        }
      } 
      return newObj;
    }
    var q = [1, 2, 4, 6, { age: 12 }, [1, 2]];
    var d = deepClone(q)
    console.log(d)

3. 函数库lodash

var _ = require('lodash');
var obj1 = {
   a: 1,
   b: { f: { g: 1 } },
   c: [1, 2, 3]
};
var obj2 = _.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);
// false

更多关于js深拷贝与浅拷贝的文章请查看下面的相关链接

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

js深拷贝与浅拷贝一文彻底搞懂

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

js数组直接赋值的问题(js数组的浅拷贝与深拷贝方法)

JS数组在直接赋值时属于数组的浅拷贝,新数组保存的是原数据的内存地址,修改新数组或原数组其中一个数组,另一个数组也会相应的变化,数组的直接赋值属于数组的浅拷贝,JS存储对象都是存内存地址
2022-11-13

一文带你认识Java中的Object类和深浅拷贝

任何变成语言中,其实都有浅拷贝和深拷贝的概念,Java中也不例外,下面这篇文章主要给大家介绍了关于Java中Object类和深浅拷贝的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
2023-05-17

编程热搜

目录