1、栈(stack)堆(heap)

  stack为自动分配的内存空间,它由系统自动释放;而heap则是动态分配的内存,大小不定也不会自动释放。       

2、基本类型和引用类型

  基本类型:存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配。

  5种基本数据类型有Undefined、Null、Boolean、NumberString,它们是直接按值存放的,所以可以直接访问。

  引用类型:存放在堆内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。每个空间大小不一样,要根据情况开进行特定的分配。

  当我们需要访问引用类型(如对象,数组,函数等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。

3、传值与传址

  前面之所以要说明什么是内存中的堆、栈以及变量类型,实际上是为下文服务的,就是为了更好的理解什么是“浅拷贝”和“深拷贝”。

  基本类型与引用类型最大的区别实际就是传值与传址的区别。测试用例:

 1     var a = [1,2,3,4,5];
2 var b = a;//传址 ,对象中传给变量的数据是引用类型的,会存储在堆中;
3 var c = a[0];//传值,把对象中的属性/数组中的数组项赋值给变量,这时变量C是基本数据类型,存储在栈内存中;改变栈中的数据不会影响堆中的数据
4 alert(b);//1,2,3,4,5
5 alert(c);//1
6 //改变数值
7 b[4] = 6;
8 c = 7;
9 alert(a[4]);//6
10 alert(a[0]);//

  从上面我们可以得知,当我改变b中的数据时,a中数据也发生了变化;但是当我改变c的数据值时,a却没有发生改变。

  这就是传值与传址的区别。因为a是数组,属于引用类型,所以它赋予给b的时候传的是栈中的地址(相当于新建了一个不同名“指针”),而不是堆内存中的对象。而c仅仅是从a堆内存中获取的一个数据值,并保存在栈中。所以b修改的时候,会根据地址回到a堆中修改,c则直接在栈中修改,并且不能指向a堆内存中。

3、浅拷贝

  前面已经提到,在定义一个对象或数组时,变量存放的往往只是一个地址。当我们使用对象拷贝时,如果属性是对象或数组时,这时候我们传递的也只是一个地址。因此子对象在访问该属性时,会根据地址回溯到父对象指向的堆内存中,即父子对象发生了关联,两者的属性值会指向同一内存空间。

 1   var a = {
2 key1:"11111"
3 }
4 function Copy(p) {
5 var c = {};
6 for (var i in p) {
7   c[i] = p[i];
8 }
9 return c;
10   }
11 a.key2 = ['小辉','小辉'];
12 var b = Copy(a);
13    b.key3 = '33333';
14 alert(b.key1); //1111111
15 alert(b.key3); //33333
16 alert(a.key3); //undefined

  a对象中key1属性是字符串,key2属性是数组。a拷贝到b,12属性均顺利拷贝。给b对象新增一个字符串类型的属性key3时,b能正常修改,而a中无定义。说明子对象的key3(基本类型)并没有关联到父对象中,所以undefined。

1 b.key2.push("大辉");
2 alert(b.key2); //小辉,小辉,大辉
3 alert(a.key2); //小辉,小辉,大辉

  但是,若修改的属性变为对象或数组时,那么父子对象之间就会发生关联。从以上弹出结果可知,我对b对象进行修改,a、b的key2属性值(数组)均发生了改变。其在内存的状态,可以用下图来表示。

  原因是key1的值属于基本类型,所以拷贝的时候传递的就是该数据段;但是key2的值是堆内存中的对象,所以key2在拷贝的时候传递的是指向key2对象的地址,无论复制多少个key2,其值始终是指向父对象的key2对象的内存空间。

4、深拷贝

  或许以上并不是我们在实际编码中想要的结果,我们不希望父子对象之间产生关联,那么这时候可以用到深拷贝。既然属性值类型是数组和或象时只会传址,那么我们就用递归来解决这个问题,把父对象中所有属于对象的属性类型都遍历赋给子对象即可。测试代码如下:

 1   function Copy(p, c) {
2 var c = c || {};
3 for (var i in p) {
4   if (typeof p[i] === 'object') {
5      c[i] = (p[i].constructor === Array) ? [] : {};
6      Copy(p[i], c[i]);
7   } else {
8      c[i] = p[i];
9   }
10 }
11 return c;
12   }
13 a.key2 = ['小辉','小辉'];
14 var b={};
15 b = Copy(a,b);
16 b.key2.push("大辉");
17 alert(b.key2); //小辉,小辉,大辉
18 alert(a.key2); //小辉,小辉

  由上可知,修改b的key2数组时,没有使a父对象中的key2数组新增一个值,即子对象没有影响到父对象a中的key2。其存储模式大致如下:

js中的栈与堆的讲解/基本数据类型与引用类型的讲解的更多相关文章

  1. js 中的栈和堆

    js中的栈与堆的讲解/基本数据类型与引用类型的讲解 前言:1. 学习前端,入门简单,想学好确实是一件很困难的事情,东西多而且杂,版本快速迭代,产品框架层出不穷. 2. 前端学习成本确实很高,需要不断的 ...

  2. js中的栈、堆、队列、内存空间

    栈(stack) .堆(heap). 队列(queue)是js的三种数据结构. 栈(stack) 栈的特点是"LIFO,即后进先出(Last in, first out)".数据存 ...

  3. JS中的栈和堆

    一.栈和堆 栈(stack):栈会自动分配内存空间,会自动释放,存放基本类型,简单的数据段,占据固定大小的空间. 基本类型:String,Number,Boolean,Null,Undefined 堆 ...

  4. js中的栈,堆。

    一.栈和堆 栈(stack):栈会自动分配内存空间,会自动释放,存放基本类型,简单的数据段,占据固定大小的空间. 基本类型:String,Number,Boolean,Null,Undefined 堆 ...

  5. 关于VS中更改栈和堆空间的大小

    编号:1008时间:2016年4月12日17:01:38功能:关于VS中更改栈和堆空间的大小 URL:http://blog.csdn.net/icerock2000/article/details/ ...

  6. 浅谈Java中的栈和堆

    人们常说堆栈堆栈,堆和栈是内存中两处不一样的地方,什么样的数据存在栈,又是什么样的数据存在堆中? 这里浅谈Java中的栈和堆 首先,将结论写在前面,后面再用例子加以验证. Java的栈中存储以下类型数 ...

  7. Java中的栈,堆,方法区和常量池

    要说Java中的栈,堆,方法区和常量池就要提到HotSpot,HotSpot是Sun JDK 和 Open JDK中所带的虚拟机. (Sun JDK 和 Open JDK除了注释不同,代码实现基本上是 ...

  8. JAVA中的栈和堆

    JAVA在程序运行时,在内存中划分5片空间进行数据的存储.分别是:1:寄存器.2:本地方法区.3:方法区.4:栈.5:堆. 基本,栈stack和堆heap这两个概念很重要,不了解清楚,后面就不用学了. ...

  9. JAVA中的栈和堆【转】

    原文链接 https://www.cnblogs.com/ibelieve618/p/6380328.html JAVA在程序运行时,在内存中划分5片空间进行数据的存储.分别是:1:寄存器.2:本地方 ...

随机推荐

  1. [总结] O(n)求和为0的最长子段

    以这题为例 Solution 我们首先用前缀和差分,可以认为G是1,R是-1,然后求一个前缀和qzh. 如果 qzh[i]==qzh[j] 那么 i~j 这一整段,一定是一个和为0的区间,即红绿相等的 ...

  2. 基于keras的BiLstm与CRF实现命名实体标注

    众所周知,通过Bilstm已经可以实现分词或命名实体标注了,同样地单独的CRF也可以很好的实现.既然LSTM都已经可以预测了,为啥要搞一个LSTM+CRF的hybrid model? 因为单独LSTM ...

  3. Redis TTL命令

    Redis TTL 命令以秒为单位返回 key 的剩余过期时间. redis TTL 命令基本语法如下: redis 127.0.0.1:6379> TTL KEY_NAME 当 key 不存在 ...

  4. 说一说Java的Unsafe类

    最近在看Java并发包的源码,发现了神奇的Unsafe类,仔细研究了一下,在这里跟大家分享一下. Unsafe类是在sun.misc包下,不属于Java标准.但是很多Java的基础类库,包括一些被广泛 ...

  5. (译文)React----React应用程序流式服务端渲染

    好处 React16推出了流式服务端渲染,它允许你并行地分发HTML片段.这样可以让渲染 出的首字节有意义的内容给用户速度更快. (例子1,上面部分是一次性转换,下面是流渲染,两种方式) 而且相对re ...

  6. 第2次作业:STEAM案例分析

    1.介绍产品的相关信息 1.1我选择的产品是STEAM 1.2选择STEAM的理由 STEAM是一个线上游戏购买平台,不同于亚马逊购买DVD光盘,它支持从游戏库购买数字发行版体验游戏.另外,它也不同于 ...

  7. 2017-2018-1 20155214&20155216 实验四:外设驱动程序设计

    2017-2018-1 20155214&20155216 实验四:外设驱动程序设计 实验四外设驱动程序设计-1 实验要求: 学习资源中全课中的"hqyj.嵌入式Linux应用程序开 ...

  8. Beta冲刺第五天

    一.昨天的困难 没有困难. 二.今天进度 1.林洋洋:日程刷新重构. 2.黄腾达:创建协作日程当选择只触发一次时自动填充1,并禁用input. 3.张合胜:修复列表显示日程重复单位的格式化. 三.明日 ...

  9. 201621123057 《Java程序设计》第10周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容 2. 书面作业 本次PTA作业题集异常 1. 常用异常 结合题集题目7-1回答 1.1 自己以前编写的代码中经常出现什 ...

  10. 201621123068 Week02-Java基本语法与类库

    1. 本周学习总结 1.1 当浮点数和整数放到一起运算时,java一般会将整数转化为浮点数然后进行浮点数计算,但是这样得出的结果通常与数学运算有一定误差,浮点数精确计算需要使用BigDecimal类 ...