文章详情

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

请输入下面的图形验证码

提交验证

短信预约提醒成功

JavaScript深拷贝与浅拷贝原理深入探究

2022-11-13 18:42

关注

一、JS中数据的存储形式-堆栈

我们先简单理解一下堆栈分别是啥:

什么是栈:计算机为原始类型开辟的一块内存空间 string number ...

什么是堆:计算机为引用类型开辟的一块内存空间 object

我们分别分析下面两段代码:

var a = 'jack'
var b = a
b = 'andy'
console.log(a,b);//jack andy
var c = {key : 1}
var d = c
d.key = 2
console.log(c,d);//{ key: 2 } { key: 2 }

看完之后我们可能有这么一个疑问,第一段代码很好理解,但是第二段代码里改变的明明是d中的key,为啥c里的key也改变了呢?

这里就是因为堆跟栈的原理,我们在定义原始类型数据的时候都会开辟一个栈的空间,当声明一个基本变量时,它就会被存储到栈内存中,而当其发生复制时,会把对应内存中的数据复制一份到新内存中,所以这两个变量之间没有什么联系。如果我们对引用类型进行复制,我们只是将地址复制了一遍,原变量和复制的新变量都是指向同一个地址,这就说明对新变量进行修改时就会影响到原变量的值。

二、深浅拷贝的三种方式

深拷贝与浅拷贝,简单点来说:

就是假设B赋值了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝。如果B没变,那就是深拷贝。

遍历赋值

下面我们看一段代码:

var obj = {
  a:'hello',
  b:{
    a:'world',
    b:111
  },
  c:[11,'jack','abdy']
}
function clone(obj) {
  var objnew = {}
  for(var i in obj) {
    objnew[i] = obj[i]
  }
  return objnew
}
var objcopy = clone(obj)
console.log(obj);
console.log(objcopy);

在这里我们定义了一个对象 obj,为了实现能够复制出另一个对象,我们再定义一个clone方法。然后调用这个方法,输出原来的对象和复制后的对象,看看是否相同:

在控制台下输出的两个结果没有任何差异,那他们两个是否真的完全一样呢?

他们两个是有不同的,因为这里的拷贝属于浅拷贝,我们根据浅拷贝的定义,如果在上例中,我们改变了objcopy,那么obj也发生了变化的话那他就是一个浅拷贝。

我们下面来验证一下,改变一下objcopy.b.a的值,看看 obj 里会不会发生相应的变化:

将objcopy.b.a赋值为字符串hhhh后,obj.b.a也变为了hhhh,这就说明我们最开始的拷贝属于浅拷贝。因为obj.b他是一个引用类型,所以objcopy.b和obj.b指向的都是同一个地址,这样不管objcopy.b.a改成什么,obj.b.a都会变成什么。

Object.create()

这种方法只需要行代码:

var objcopy = Object.create(obj)

obj在复制的时候,它会被当前对象复制到原型__proto__上,并不是复制到当前的对象上。我们再次改变一下objcopy.b.a的值,看看 obj 里会不会发生相应的变化:

所以他也是浅拷贝

遍历赋值实现深拷贝

这是深拷贝的克隆函数:

function deepclone(startobj,endobj) {
  var obj = endobj || {}
  for(var i in startobj)
  {
    if(typeof startobj[i] === 'object') {
      obj[i] = startobj[i].constructor === Array ? [] : {}
      deepclone(startobj[i],obj[i])
    }else {
      obj[i] = startobj[i]
    }
  }
  return obj
}

值得注意的一点是,在递归调用的时候,需要把当前处理的 obj[i] 给传回去,否则的话 每次递归obj都会被赋值为空对象,就会对已经克隆好的数据产生影响。

我们来验证一下是否是深拷贝:

var objcopy = deepclone(obj)
objcopy.b.a = 'hhhh'
console.log(obj);
console.log(objcopy);

运行结果:

这就说明我们的深拷贝已经实现了。

通过JSON.parse()和JSON.stringify()实现深拷贝

这是我们在工作中最常见的一种方式

var objcopy = JSON.parse(JSON.stringify(obj))

我们对初始化的对象先通过JSON.stringify转换为字符串,再通过JSON.parse转回对象类型。

这样为什么能实现深拷贝的效果呢?因为我们通过 JSON.stringify 转成 string 类型后,他就存储在栈里,这样就不会出现地址值上的误会了,再通过JSON.parse就可以再转换为object类型。

到此这篇关于JavaScript深拷贝与浅拷贝原理深入探究的文章就介绍到这了,更多相关JS深拷贝与浅拷贝内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

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

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

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     801人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     348人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     311人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     432人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     220人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯