27岁,山西运城人,职业电商经理人,前端开发工作者,从事过网站建设、网络推广、SEO、SEM、信息流推广、二类电商、网络运维、软件开发,等相关电商工作,经验较为丰富,小米技术社区致力于为广大从事Web前端开发的人员提供一些力所能及的引导和帮助 ...[更多]
E-mail:mzze@163.com
Q Q:32362389
W X:xiaomi168527
27岁,山西运城人,职业电商经理人,网络工程师兼运维,从事过运营商网络建设,企业网络建设、优化。数据中心网络维护等通过,经验丰富,座右铭:当自己休息的时候,别忘了别人还在奔跑。 ...[更多]
大于花一样的年龄,河南郑州是我家,2010年在北京接触团购网,2011年进入天猫淘宝一待就是四年,如今已经将设计走向国际化(ps:误打误撞开始进入阿里巴巴国际站的设计,嘿嘿)五年电商设计,丰富经验,从事过天猫淘宝阿里各项设计,店铺运营,产品拍摄;我将我的经历与您分享是我的快乐!座右铭:越努力越幸运! ...[更多]
E-mail:97157726@qq.com
Q Q:97157726
值传递 :基本数据类型,直接将变量放在栈区的值,复制一份,传给另外一个变量。
引用传递:对象类型,将变量放在堆区的值的地址,传给另外一个变量。
要了解以上概念,我们先了解js内存数据存储的机制.
内存里面划分为不同的区,存不同的东西(和电脑盘一样),内存存储主要划分为5个区域:
存放简单类型的数据,操作比较快,但程序员是无法控制的。
增值类型:向下增长 先来的数据放在最下面,一开始的序号大
空间大小:很小 只有2M左右
由编译器自动分配释放 ,存放函数的参数值,局部变量的值等,内存的分配是连续的,类似于平时我们所说的栈,如果还不清楚,那么就把它想成数组,它的内存分配是连续分配的,即,所分配的内存是在一块连续的内存区域内.当我们声明变量时,那么编译器会自动接着当前栈区的结尾来分配内存.
在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。
基本类型:非对象的string number boolean undefined null 数据直接存储在栈区
存放复杂数据,操作比较慢
增值类型:向上增长 一开始的序号小
一般由程序员分配释放, 若程序员不释放,程序结束时可能由操作系统回收.类似于链表,在内存中的分布不是连续的,它们是不同区域的内存块通过指针链接起来的.一旦某一节点从链中断开,我们要人为的把所断开的节点从内存中释放.
堆是向高地址扩展的数据结构,是不连续的内存区域。
空间大小: 很大,随便存,数据变量多没问题
引用类型: 对象(array object function) 堆区存数据, 栈区存数据在堆区的地址
js里面基本用不上,因为变量基本不存在静态变量
全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 程序结束后由系统释放
CS6之前没有常量,从CS6才开始有
常量字符串就是放在这里的。 程序结束后由系统释放
放置函数体,比如定义一个函数,大括号里面的函数体
速度区别
栈由系统自动分配,速度较快。但程序员是无法控制的。
堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.
另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,它不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存,虽然用起来最不方便。但是速度快,也最灵活。
栈: 在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。
char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在运行时刻赋值的;
而bbbbbbbbbbb是在编译时就确定的;
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。
堆和栈的区别可以用如下的比喻来看出:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。
基本类型:非对象 string number boolean undefined null 数据直接存储在栈区
let a =1 ; let b =1;
变量 | 栈区 | 堆区 |
a | 1 | |
b | 1 |
var a = 1; var b = a; b = 2;
变量 | 栈区 | 堆区 |
a | 1 | |
b | 2 |
引用类型:对象(array object function) 堆区存数据, 栈区存数据在堆区的地址
var obj = {"age":40, "sex":"男"};
变量 | 栈区 | 堆区 |
obj | 00000001(堆区地址) | {"age":40, "sex":"男"} |
b | 2 |
var obj = {"age":40, "sex":"男"}; var obj2 = obj;
变量 | 栈区 | 堆区 |
obj | 00000001(堆区地址) | {"age":40, "sex":"男"} |
obj2 | 00000001 | 这里还是指向上面那个堆区 |
var obj = {"age":40, "sex":"男"}; var obj2 = obj; obj2.age = 30;
变量 | 栈区 | 堆区 |
obj | 00000001(堆区地址) | {"age":30, "sex":"男"} //修改了这里的40为30 |
obj2 | 00000001 |
//普通值(基本类型) var a = 1; var b = a; console.log(a, b);//结果为1,2 b = 2; console.log(a, b); //结果为1,2 //特殊的---对象(复杂类型) var obj = {"age":40, "sex":"男"}; var obj2 = obj; console.log(obj, obj2); //结果为2个{"age":40, "sex":"男"}; obj2 = {'age':30}; console.log(obj, obj2); //结果为2个{"age":30, "sex":"男"}; 疑问?为什么只修改了obj2,1也改了 //说明 obj 和 obj2两个变量,存储的是一个对象,是共用的 //函数参数 如果是对象 function fn(m){ m.age = 30; console.log(m); } var obj = {"age":40, "sex":"男"}; fn(obj); console.log(obj); //obj.age被改为 30
本站内容均为小米原创,转载请注明出处:小米技术社区>> js数据在内存中的存储[值传递]和[引用传递]以及栈区和堆区的区别