资讯专栏INFORMATION COLUMN

详解js深浅复制问题

X1nFLY / 506人阅读

摘要:二这么分的好处就是在于节省内存资源,便于合理回收内存详解中的深浅复制有了上面的铺垫,那么我们理解起深浅复制就变得容易的许多。

前言

对于前端开发来说,我们经常能够遇到的问题就是js的深浅复制问题,通常情况下我们解决这个问题的方法就是用JSON.parse(JSON.Stringify(xx))转换或者用类似于Inmmutable这种第三方库来进行深复制,但是我们还是要弄懂其中原理,这样在开发过程中可以省掉很多的坑。

首先让我们看几个例子
// eg1(操作原对象对复制对象无影响):
var a = "a";
var b =a;
a = "c";
console.log(b); // a

// eg2(操作原对象对复制对象有影响):
var a = {
a:"a"
};
var b =a;
a.a = "c";
console.log(b); // {a:"c"}

// eg3(操作原对象对复制对象无影响):
var a = {
a:"a"
};
var b =a.a;
a.a = "c";
console.log(b); // a

// eg4(操作复制对象对原对象有影响):
var a = {
a:"a"
};
var b = a
b.b = "b";
console.log(a); // {a:"a",b:"b"}
// eg5(操作复制对象对原对象没有影响):
var a = {
a:"a"
};
var b = a;
b = {
b:"b"
}
console.log(a); // {a:"a"}

想要理解上面例子发生的原因就要从数据类型和堆栈内存开始说起

基本数据类型于引用数据类型

js中存在着两种数据类型:基本数据类型引用数据类型;
基本数据类型包括:Number、String 、Boolean、Null和Undefined这些常见类型
引用数据类型包括: Object 、Array 、Function这些对象类型

堆内存和栈内存

在大多数编程语言中,都存在着这样的两个内存空间一个是堆内存(heap),另一个是栈内存(stack)
当我们存储一个基本数据类型的时候,我们直接放到栈内存中。而当我们存储一个引用数据类型的时候,我们将实际内容存储在堆内存当中,同时在栈内存中存放着该内容的引用,也就是一个指针
为什么我们这么做呢?简单来说有两点,一是因为栈内存中存放大小固定的数据,即基本数据类型的数据,同时引用数据类型的指针也是大小固定的,也可以放进栈内存中,方便程序查找这个数据;而堆内存中存放的是大小不固定的数据,所以适合存放引用数据类型。二这么分的好处就是在于节省内存资源,便于os合理回收内存

详解js中的深浅复制

有了上面的铺垫,那么我们理解起深浅复制就变得容易的许多。
首先我们要记住:当我们复制一个基本数据类型的数据时,是新建一个数据同时存放到栈内存中,而当我们复制一个引用数据类型时,是复制这个引用数据类型的地址,存放到栈内存中,此时堆内存中并没有任何变化
让我们来看之前的例子
例一和例二就没什么好说的了,我们从例三开始:
a.a是一个字符串类型,是基本类型,所以当b复制的时候是直接复制了一个存放到栈内存中,当a改变时,对b没有影响
例四:
a是一个对象,是引用数据类型,所以当b复制的时候是复制了a的指针,当对a和b操作时,仍然操作的是堆内存中同一对象,所以a会发生改变
例五:
这个例子看似和上面的很像但实际有很大不同,b = {b:"b"}这个操作实际上是新建了一个对象
也就是说在堆内存中新建了一个地方,来存放{b:"b"}同时将栈内存中b原来存储的指向a的指针指向了这个对象,多以a并未发生任何改变

参考文献

https://segmentfault.com/a/11...(重点看这篇,写的很好!)
http://blog.csdn.net/flyingpi...
https://www.cnblogs.com/cxyin...

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

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

相关文章

  • 详解js深浅复制

    摘要:从而也引出了所谓的深浅复制问题。附注对于浅复制,其实还有其他的实现方式,比如数组中和方法,对于这些还是希望大家自己了解,本本主要针对深浅复制的实现原理进行解析。 前言 在之前写继承的过程谈到了深浅复制的问题,因为有读者反映到需要解析,趁今天周末写一篇解析,今天的主体相对之前来说理解难度低一些,篇幅可能也比较短,诸君按需阅读即可。 从两种数据类型说起 在js中,变量的类型可以大致分成两种...

    Lin_YT 评论0 收藏0
  • 前端进击的巨人(二):栈、堆、队列、内存空间

    摘要:中有三种数据结构栈堆队列。前端进击的巨人一执行上下文与执行栈,变量对象中解释执行栈时,举了一个乒乓球盒子的例子,来演示栈的存取方式,这里再举个栗子搭积木。对于基本类型,栈中存储的就是它自身的值,所以新内存空间存储的也是一个值。 面试经常遇到的深浅拷贝,事件轮询,函数调用栈,闭包等容易出错的题目,究其原因,都是跟JavaScript基础知识不牢固有关,下层地基没打好,上层就是豆腐渣工程,...

    edgardeng 评论0 收藏0
  • JS专题之深浅拷贝

    摘要:在之前的文章专题之数据类型和类型检测中我有讲过,中的数据类型分为两种,基本数据类型和引用数据类型,基本数据类型是保存在栈的数据结构中的是按值访问,所以不存在深浅拷贝问题。 前言 在开发过程中,偶尔会遇到这种场景,拿到一个数据后,你打算对它进行处理,但是你又希望拷贝一份副本出来,方便数据对比和以后恢复数据。 那么这就涉及到了 JS 中对数据的深浅拷贝问题,所谓深浅拷贝,浅拷贝的意思就是,...

    ASCH 评论0 收藏0
  • 复习Javascript专题(四):js中的深浅拷贝

    摘要:基本数据类型的复制很简单,就是赋值操作,所以深浅拷贝也是针对,这类引用类型数据。它会抛弃对象的。另外,查资料过程中还看到这么一个词结构化克隆算法还有这一篇资料也有参考,也写得比较详细了的深浅拷贝 基本数据类型的复制很简单,就是赋值操作,所以深浅拷贝也是针对Object,Array这类引用类型数据。 浅拷贝对于字符串来说,是值的复制,而对于对象来说则是对对象地址的复制;而深拷贝的话,它不...

    MobService 评论0 收藏0
  • 深入理解JS深浅拷贝

    摘要:深拷贝相比于浅拷贝速度较慢并且花销较大。所以在赋值完成后,在栈内存就有两个指针指向堆内存同一个数据。结果如下扩展运算符只能对一层进行深拷贝如果拷贝的层数超过了一层的话,那么就会进行浅拷贝那么我们可以看到和展开原算符对于深浅拷贝的结果是一样。 JS中数据类型 基本数据类型: undefined、null、Boolean、Number、String和Symbol(ES6) 引用数据类型:...

    JackJiang 评论0 收藏0

发表评论

0条评论

X1nFLY

|高级讲师

TA的文章

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