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 ...
随机推荐
- background 背景图片 在IE8中不显示解决方法
我给ul加了一个背景图片 background 火狐 ie9 ch都显示.唯独在IE8中不显示 之前的样式代码 background: url( rgba(, , , ); 在ie8中改成 backg ...
- MQTT协议学习研究 & Mosquitto简要教程(安装和使用)
若初次接触MQTT协议,可先理解以下概念: [MQTT协议特点]——相比于RESTful架构的物联网系统,MQTT协议借助消息推送功能,可以更好地实现远程控制. [MQTT协议角色]——在RESTfu ...
- c/c++的预处理定义 Stringizing Operator (#) Charizing Operator (#@) Token-Pasting Operator (##)
c/c++的预处理定义:一.Stringizing Operator (#)在c和c++中数字标志符#被赋予了新的意义,即字符串化操作符.其作用是:将宏定义中的传入参数名转换成用一对双引号括起来参数名 ...
- wordpress 修改域名后的403
wordpress的好处就是方便,不好呢,额,反正就是有. 最近,修改域名,也遇到了这个问题[修改域名后,出现403]. 网上的办法似乎有很多,但有一些并不好,比如修改数据库什么的,如果是新手,数据库 ...
- OnClick,OnClientClick和OnServerClick的区别
OnClientClick是客户端事件处理方法,一般采用JavaScript来进行处理,也就是直接在IE端运行,一点击就运行 OnClick是服务器端事件处理方法,在服务器端也就是IIS中运行, ...
- tensorflow训练自己的数据集实现CNN图像分类1
利用卷积神经网络训练图像数据分为以下几个步骤 读取图片文件 产生用于训练的批次 定义训练的模型(包括初始化参数,卷积.池化层等参数.网络) 训练 1 读取图片文件 def get_files(file ...
- Gson(Google)基础
一.所需jar包: gson-x.x.jar(本例使用的是gson-2.7.jar). 二.解析转化: 1.json字符串 < ------ > json String str=&qu ...
- python函数里面,一个*是可变参数的元祖,两个*是可变参数的字典
python的函数中,有时会有类似*args,**keys这样的参数,代表的是可变参数,一个*表示元祖,两个*表示字典,就是说这个函数可以接受任何类型的参数,都不会报错,有些函数为了提高可用性,会加这 ...
- Zookeeper学习记录(二):使用以及配置
zookeeper已经介绍了它的原理设计以及实现方式,我们接下来介绍zookeeper的使用方法以及简单配置. 下载 获取Zookeeper的发布包,从Apache下载映像中下载一个最新稳定版本. 单 ...
- Git 的安装步骤
Git 的安装步骤 一.下载Git Git 的官网:https://git-scm.com/ 在 Git 的官网中点击Downloads,进入如下页面: 选择对应的操作系统,以博主为例,点击Windo ...