js 中的 堆栈
1.含义及对比
堆和栈都是运行时内存中分配的一个数据区,因此也被称为堆区和栈区;
二者存储的数据类型和处理速度不同;
堆(heap)用于复杂数据类型(引用类型)分配空间,例如数组对象、object对象;它是运行时动态分配内存的,因此存取速度较慢。
栈(stack)中主要存放一些基本类型的变量和对象的引用,(包含池,池存放常量),其优势是存取速度比堆要快,并且栈内的数据可以共享,但缺点是存在栈中的数据大小与生存期必须是确定的,缺乏灵活性,
先进后出,后进先出原则,所以 push 优于 unshift
1.1 扩展: 队列(先进先出(FIFO)的数据结构,这是事件循环(Event Loop)的基础结构)
1.2 经典面试题
var a = 20;
var b = a; // b 为栈类型,相当于新开一块空间然后赋值为 20,不影响原来的a
b = 30;
console.log(a)
console.log(b)
//20 30
var a = { name: '前端开发' }
var b = a;
b.name = '进阶';
console.log(a)
console.log(b)
// { name: '进阶' } name: '进阶' }
var a = { name: '前端开发' }
var b = a;
a = null; //释放引用
console.log(a)
console.log(b)
// null { name: '前端开发' }
var a = {n: 1};
var b = a;
a.x = a = {n: 2}; // 等价于 b.x = a = {n: 2}; 先是预编译ab同时指向的对象增加x属性,该对象也就是后来都没变的b指向的对象,这里 a= {n: 2};改变了a的指向。
另外扩展下连等算法: var a=b=1,b为全局变量了 function t(){ var var a=b=1} t() b // 1 a // undefined
console.log(a.x);
console.log(b.x);
// undefined {n:2}
1.3 闭包中的变量并不保存中栈内存中,而是保存在堆内存
中,这也就解释了函数之后之后为什么闭包还能引用到函数内的变量。
function A() { let a = 1 function B() { console.log(a) } return B }
1.4 垃圾回收算法 ( 常见内存泄漏:全局变量、定时器、闭包、dom引用 )
- 引用计数(现代浏览器不再使用) 循环引用 问题 function cycle() { var o1 = {}; var o2 = {}; o1.a = o2; o2.a = o1; return "cycle reference!" } cycle();
- 标记清除(常用) 从根部(在JS中就是全局对象)出发定时扫描内存中的对象,凡是能从根部到达的对象,保留。那些从根部出发无法触及到的对象被标记为不再使用,稍后进行回收。
2.例子
栈
var a=3;
var b=3;
先处理 var a=3;,首先会在栈中创建一个变量为a引用,然后查找栈中是否有3这个值,如果没有找到,就将3存放进来,然后将a指向3。
接着处理 var b=3;,在创建为b的引用变量后,查找栈中是否有3这个值,因为此时栈中已经存在了3,便将b直接指向3。这样,就出现了a与b同时指向3的情况。
此时,如果再令a=4,那么JavaScript解释引擎会重新搜查栈中是否有4这个值,如果已经有了,则直接将a指向这个地址。没有的话直接压入并指向它。 堆
var fruit_1="apple";
var fruit_2="orange";
var fruit_3="banana";
var oArray=[fruit_1,fruit_2,fruit_3]; (此时相当于新建一个包含三个值的数组,与 fruit等不再相关)
var newArray=oArray;
当创建数组时,就会在堆内存创建一个数组对象,并且在栈内存中创建一个对数组的引用
变量fruit_1、fruit_2、fruit_3为基本数据类型,它们的值直接存放在栈中
newArray、oArray为复合数据类型(引用类型),他们的引用变量存放在栈中, 指向于存放在堆中的实际对象。 比较
var str=new String('abc');
var str='abc';
第一种是用new关键字来新建String对象,对象会存放在堆中,每调用一次就会创建一个新的对象,而不管其字符串值是否相等及是否有必要创建新对象,从而加重了程序的负担。并且堆的访问速度慢。
第二种是在栈中,栈中存放值‘abc’和对值的引用;这种写法在内存中只存在一个值,有利于节省内存空间。同时它可以在一定程度上提高程序的运行速度,因为存储在栈中,其值可以共享,并且由于栈访问更快;
var str1='abc';
var str2='abc';
alert(str1==str2); // true
alert(str1===str2); // true
var str1=new String('abc');
var str2=new String('abc');
alert(str1==str2); // false
alert(str1===str2); // false
3.细节
JavaScript堆不需要程序代码来显示地释放,因为堆是由自动的垃圾回收来负责的,每种浏览器中的JavaScript解释引擎有不同的自动回收方式
一个最基本的原则是:如果栈中不存在对堆中某个对象的引用,那么就认为该对象已经不再需要,在垃圾回收时就会清除该对象占用的内存空间。
因此,在不需要时应该将对对象的引用释放掉(newArray=null;),以利于垃圾回收,这样就可以提高程序的性能。
4. 相关文章
JavaScript是如何工作的:引擎,运行时和调用堆栈的概述!
js 中的 堆栈的更多相关文章
- 【repost】JS中的异常处理方法分享
我们在编写js过程中,难免会遇到一些代码错误问题,需要找出来,有些时候怕因为js问题导致用户体验差,这里给出一些解决方法 js容错语句,就是js出错也不提示错误(防止浏览器右下角有个黄色的三角符号,要 ...
- Node.js权威指南 (10) - Node.js中的错误处理与断言处理
10.1 使用domain模块处理错误 / 272 10.1.1 domain模块概述 / 272 10.1.2 创建并使用Domain对象 / 274 10.1.3 隐式绑定与显式绑定 / 276 ...
- js 中的栈和堆
js中的栈与堆的讲解/基本数据类型与引用类型的讲解 前言:1. 学习前端,入门简单,想学好确实是一件很困难的事情,东西多而且杂,版本快速迭代,产品框架层出不穷. 2. 前端学习成本确实很高,需要不断的 ...
- 【面试篇】寒冬求职季之你必须要懂的原生JS(中)
互联网寒冬之际,各大公司都缩减了HC,甚至是采取了“裁员”措施,在这样的大环境之下,想要获得一份更好的工作,必然需要付出更多的努力. 一年前,也许你搞清楚闭包,this,原型链,就能获得认可.但是现在 ...
- js中的栈、堆、队列、内存空间
栈(stack) .堆(heap). 队列(queue)是js的三种数据结构. 栈(stack) 栈的特点是"LIFO,即后进先出(Last in, first out)".数据存 ...
- 浅析JS中的堆内存与栈内存
最近跟着组里的大佬面试碰到这么一个问题, Q:说说var.let.const的区别 A:balabalabalabla... Q:const定义的值能改么? A:你逗我?不能吧 不知道各位看官怎么想? ...
- 【转】Js中Prototype、__proto__、Constructor、Object、Function关系介绍
一 Prototype.__proto__与Object.Function关系介绍 Function.Object:Js自带的函数对象. prototype,每一个 ...
- Vue.js中,如何自己维护路由跳转记录?
在Vue的项目中,如果我们想要做返回.回退操作时,一般会调用router.go(n)这个api,但是实际操作中,使用这个api有风险,就是会让用户跳出当前应用,因为它记录的是浏览器的访问记录,而不是你 ...
- js中的函数function
js的function对象在调用过程中具有一个arguments的属性,它是由脚本解释器创建的(这也是arguments创建的唯一方式). arguments属性能够看作是一个Array对象,它有le ...
随机推荐
- MongoDB 工具助手类(.NET)
在开发过程中,需要用到MongoDB,本身MongoDB自己对类的封装就特别好了.为了更加符合我们平时的开发使用,我现在进行了一个简单的封装操作. 连接数据库类:MongoDBContext usin ...
- ef延迟加载不到导航属性问题
最近做项目踩到了一个ef问题上的坑,导航属性(外键关键,如子表或主表等)“.”出来后是Null,外键值也对,数据库和ef的关系配置也都正确,就是加载不出来.后来发现实体里导航属性前少了个virtual ...
- Bus,Exclusive access,memory attribute
指令LDREX,STREX是在armv6中新加的指令,配合AMBA3--AXI中的lock[1:0]信号. 在Atomic Access一节中是这么规定的:ARLOCK[1:0]/AWLOCK[1:0 ...
- Loadrunder场景设计篇——添加windows Resource计数器和指标说明
目的 监控要测试的windows服务器的资源使用情况 A.添加计数器步骤 1.添加视图,方法双击.拖动左侧的Windows Rescources到右边图形区,或右键右侧已有视图,Open a New ...
- linux常用命令:wget 命令
wget命令用来从指定的URL下载文件.wget非常稳定,它在带宽很窄的情况下和不稳定网络中有很强的适应性,如果是由于网络的原因下载失败,wget会不断的尝试,直到整个文件下载完毕.如果是服务器打断下 ...
- python xml childNodes,childNodes[1].childNodes[0].data例子
xml: <?xml version='1.0' encoding='utf-8'?><!--this is a test about xml--><booklist t ...
- 2018-2019-2 20165209 《网络对抗技术》Exp4:恶意代码分析
2018-2019-2 20165209 <网络对抗技术>Exp4:恶意代码分析 1 基础问题回答和实验内容 1.1基础问题回答 如果在工作中怀疑一台主机上有恶意代码,但只是猜想,所有想监 ...
- Linux服务器---安装apache
Apache安装 1.安装Apache,使用命令“yum install httpd -y” [root@localhost ~]# yum install httpd -y Loaded pl ...
- python之路----进程二
守护进程 会随着主进程的结束而结束. 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic ...
- 关于webpack的path和publicPath。
path:所有输出文件的目标路径; publicPath:输出解析文件的目录,url 相对于 HTML 页面 区别:path是webpack所有文件的输出的路径,必须是绝对路径,比如:output输出 ...