javascript - 引用对象赋值 深浅拷贝 jquery.extend

查看:93
本文介绍了javascript - 引用对象赋值 深浅拷贝 jquery.extend的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

引用类型赋值给另一引用类型,它们只是都是指向的同一个地址,操作间相互影响。
深拷贝,就是重新分配空间,让它跟之前的对象或者数组不受影响。
浅拷贝就是等同于引用类型的赋值。

var a={banner:{size:1,weight:'0.5kg'}};
var b={apple:{size:1},banner:{size:3}};
$.extend(true,a,b)=>{banner:{size:3,weight:'0.5kg'},apple:{size:1}};
$.extend(a,b)=>{banner:{size:3},apple:{size:1}};

我看过jquery源码,深拷贝是要进行递归的。
但是我不理解,跟相互影响有什么关系,还是说我上面的概念理解错误

解决方案

浅拷贝

仅对object顶层键进行遍历和重新赋值(给对应的引用),例如:

var a = {
  x: {
    name: 'x',
    value: 10,
  },
  y: 10,
  o: {},
}
var b = {
  x: {
    name: 'x2',
    value: 20,
  },
  y: {
    name: 'y2',
    value: 20,
  },
  z: {}
}

$.extend(a, b)

这个过程里面,从b中取出所有顶层元素,即b.x, b.y, b.z,然后将它们一一赋值给a对应的键,所以最后a就有了新的a.x, a.y, a.z,同时,a.o还保留在a中,这时a.x === b.x, a.y === b.y, a.z === b.z,因为它们都是指向同一个对象的引用。既然是引用,当你操作a.x的时候,比如a.x.name = 'x3',那么b.x.name也就变成了'x3'。

深拷贝

深拷贝将深入对象元素的末层进行重新赋值,而非引用。就拿上面的a,b举例,执行:

$.extend(true, a, b)

将会深入b内部进行遍历,拿每一个节点的值与a对应(一模一样)的节点进行比较,如果不同则为a开辟存储空间,把值赋进去,如果a不存在这个节点,就为它创建后赋值进去。a的第一层子节点跟b第一层不存在相等关系,连==都不成立。

深拷贝后,a原有的一些节点会保留下来,b给过去的节点会覆盖或增加,但是和b之间不存在任何引用关系,所以修改a的任何一个节点,都不会影响b。这在一些数据处理的时候非常有用,为了不影响原始数据,需要在处理数据之前深拷贝一份再进行处理。

深拷贝的时候,数组的索引号被当做键名对待,所以数组元素会被修改,而不是被添加到原始数据中。比如:

var a = [
  {
    x: 1,
  }, 
  {
    x: 2,
  },
]
var b = [
  {
    y: 2
  },
]
$.extend(true, a, b) 

将会得到:

var a = [
  {
    x: 1,
    y: 2
  }, 
  {
    x: 2,
  },
]

b的第一个原始被合并到a的第一个元素里面去了,这个合并是因为数组按照元素的索引号作为键来进行操作。所以,合并数组不能用extend,而应该考虑用merge或concat。

这篇关于javascript - 引用对象赋值 深浅拷贝 jquery.extend的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆