浅析JS中的堆内存与栈内存
最近跟着组里的大佬面试碰到这么一个问题,
Q:说说var、let、const的区别
A:balabalabalabla...
Q:const定义的值能改么?
A:你逗我?不能吧
不知道各位看官怎么想?答案是部分能改,部分不能改。const定义的基本类型不能改变,但是定义的对象是可以通过修改对象属性等方法来改变的。如,
>>> const a = 1
>>> a
<<< 1
>>> a = 2
<<< VM1750:1 Uncaught TypeError: Assignment to constant variable.
at <anonymous>:1:3
(anonymous) @ VM1750:1
>>> const b = {}
>>> b
<<< {}
>>> b.name = 1
>>> b
<<< {name: 1}
>>> b = {}
<<< VM1785:1 Uncaught TypeError: Assignment to constant variable.
at <anonymous>:1:4
const不是定义常量么?为什么还能改?这就是我们今天要说的重点~
js中的堆内存与栈内存
在js引擎中对变量的存储主要有两种位置,堆内存和栈内存。
和java中对内存的处理类似,栈内存主要用于存储各种基本类型的变量,包括Boolean、Number、String、Undefined、Null,**以及对象变量的指针,这时候栈内存给人的感觉就像一个线性排列的空间,每个小单元大小基本相等。
而堆内存主要负责像对象Object这种变量类型的存储,如下图

栈内存中的变量一般都是已知大小或者有范围上限的,算作一种简单存储。而堆内存存储的对象类型数据对于大小这方面,一般都是未知的。个人认为,这也是为什么null作为一个object类型的变量却存储在栈内存中的原因。
因此当我们定义一个const对象的时候,我们说的常量其实是指针,就是const对象对应的堆内存指向是不变的,但是堆内存中的数据本身的大小或者属性是可变的。而对于const定义的基础变量而言,这个值就相当于const对象的指针,是不可变。
既然知道了const在内存中的存储,那么const、let定义的变量不能二次定义的流程也就比较容易猜出来了,每次使用const或者let去初始化一个变量的时候,会首先遍历当前的内存栈,看看有没有重名变量,有的话就返回错误。
说到这里,有一个十分很容易忽略的点,之前也是自己一直没有注意的就是,使用new关键字初始化的之后是不存储在栈内存中的。为什么呢?new大家都知道,根据构造函数生成新实例,这个时候生成的是对象,而不是基本类型。再看一个例子
var a = new String('123')
var b = String('123')
var c = '123'
console.log(a==b, a===b, b==c, b===c, a==c, a===c)
>>> true false true true true false
console.log(typeof a)
>>> 'object'
我们可以看到new一个String,出来的是对象,而直接字面量赋值和工厂模式出来的都是字符串。但是根据我们上面的分析大小相对固定可预期的即便是对象也可以存储在栈内存的,比如null,为啥这个不是呢?再继续看
var a = new String('123')
var b = new String('123')
console.log(a==b, a===b)
>>> false false
很明显,如果a,b是存储在栈内存中的话,两者应该是明显相等的,就像null === null是true一样,但结果两者并不相等,说明两者都是存储在堆内存中的,指针指向不一致。
说到这里,再去想一想我们常说的值类型和引用类型其实说的就是栈内存变量和堆内存变量,再想想值传递和引用传递、深拷贝和浅拷贝,都是围绕堆栈内存展开的,一个是处理值,一个是处理指针。
内存分配和垃圾回收
一般来说栈内存线性有序存储,容量小,系统分配效率高。而堆内存首先要在堆内存新分配存储区域,之后又要把指针存储到栈内存中,效率相对就要低一些了。
垃圾回收方面,栈内存变量基本上用完就回收了,而推内存中的变量因为存在很多不确定的引用,只有当所有调用的变量全部销毁之后才能回收。
继续往下思考的话,其中还有很多的东西需要去学习,今天先到这里,后续再来补充。
话说~NaN会不会也是存储在堆内存中的呢?大家想想吧,欢迎大家来一起讨论讨论~文中如有错误欢迎指出~
浅析JS中的堆内存与栈内存的更多相关文章
- 浅析js中的堆和栈
这里先说两个概念:1.堆(heap)2.栈(stack)堆 是堆内存的简称.栈 是栈内存的简称.说到堆栈,我们讲的就是内存的使用和分配了,没有寄存器的事,也没有硬盘的事.各种语言在处理堆栈的原理上都大 ...
- Java堆空间Vs栈内存
之前我写了几篇有关Java垃圾收集的文章之后,我收到了很多电子邮件,请求解释Java堆空间,Java栈内存,Java中的内存分配以及它们之间的区别. 您可能在Java,Java EE书籍和教程中看到很 ...
- JS中的堆内存与栈内存
在js引擎中对变量的存储主要有两种位置,堆内存和栈内存. 和java中对内存的处理类似,栈内存主要用于存储各种基本类型的变量,包括Boolean.Number.String.Undefined.Nul ...
- 浅析JAVA中堆内存与栈内存的区别
Java把内存划分成两种:一种是栈内存,一种是堆内存. 一.栈内存 存放基本类型的变量,对象的引用和方法调用,遵循先入后出的原则. 栈内存在函数中定义的“一些基本类型的变量和对象的引用变量”都 ...
- 了解 js 堆内存 、栈内存 。
js中的堆内存与栈内存 在js引擎中对变量的存储主要有两种位置,堆内存和栈内存. 和java中对内存的处理类似,栈内存主要用于存储各种基本类型的变量,包括Boolean.Number.String.U ...
- Java中堆内存和栈内存详解2
Java中堆内存和栈内存详解 Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,ja ...
- Java SE之Java中堆内存和栈内存[转/摘]
[转/摘]1-3Java中堆内存和栈内存 注解:内存(Memory)即 内存储器,主存,其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器(辅存)交换的数据. Java中把内存分为两种:栈 ...
- 熟悉java堆内存和栈内存和mysql的insert语句中含有id的处理
java的堆内存和栈内存有什么区别呢? 如果mysql数据库表的id是递增的,如果没有插入id,则id自增,如果插入id,则插入什么就显示什么.
- 浅析JS中的模块规范(CommonJS,AMD,CMD)////////////////////////zzzzzz
浅析JS中的模块规范(CommonJS,AMD,CMD) 如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范咯,我也听过,但之前也真的是听听而已. ...
随机推荐
- 在SQLSERVER中如何检测一个字符串中是否包含另一个字符串
--当charindex返回值大于0时则包含 为0不包含 select CHARINDEX('456','123456') SQL语句使用CHARINDEX函数,来测试一个字符串中是否包含另一个字 ...
- 【转】Java 异步处理简单实践
同步与异步 通常同步意味着一个任务的某个处理过程会对多个线程在用串行化处理,而异步则意味着某个处理过程可以允许多个线程同时处理. 异步通常代表着更好的性能,因为它很大程度上依赖于缓冲,是典型的使用空间 ...
- SpringBoot+thymelates入门
在pom.xml当中加入这俩个依赖 <dependency> <groupId>org.springframework.boot</groupId> <art ...
- Spring界的HelloWorld
1.Spring依赖的jar包下载网址: https://repo.spring.io/webapp/#/artifacts/browse/tree/General/libs-release-loca ...
- Springboot拦截器未起作用
之前遇到要使用springboot拦截器却始终未生效的状况,查了网上的博客,大抵都是@Component,@Configuration注解未加,或是使用@ComponentScan增加包扫描,但是尝试 ...
- win32FTP程序设计
掌握socket基于事件机制的网络程序设计,掌握多线程技术的FTP Server端设计方法,掌握FTP标准基本协议及其程序的实现,掌握文件内容的网络传输设计方法. 利用CFtpServer类接收和解析 ...
- sql SUM求和
- 从项目中学习HTML+CSS
最近由于工作原因以及自己的懈怠,已经很久都没有更新过博客了.通过这段时间,我发现坚持一件事情是真的很难,都说万事开头难,但是在放弃这件事上好像开头了后面就顺理成章的继续下去了.中间即使不怎么情愿也在努 ...
- springboot中使用druid和监控配置
如果想要监控自己的项目的访问情况及查看配置信息,druid是一个很好的选择,可能你会问druid是什么?有什么用?优点是什么? Druid简介 Druid是阿里巴巴开源的数据库连接池,号称是Java语 ...
- js原生实现轮播
前两天同事面试新人,让现场写”轮播的实现”.我一想这玩意貌似我也没写过啊,就在旁边暗搓搓地拖了一张纸也在那写,同事都纳闷了! 这玩意实现方法有很多种,就看喜欢那种,喜欢怎么写而已.我这里是通过对img ...