最近跟着组里的大佬面试碰到这么一个问题,

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 :1:3

(anonymous) @ VM1750:1

>>> const b = {}

>>> b

<<< {}

>>> b.name = 1

>>> b

<<< {name: 1}

>>> b = {}

<<< VM1785:1 Uncaught TypeError: Assignment to constant variable.

at :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会不会也是存储在堆内存中的呢?大家想想吧,欢迎大家来一起讨论讨论~文中如有错误欢迎指出~

python变量存储 堆与栈内存内存_浅析JS中的堆内存与栈内存相关推荐

  1. uniapp 获取到js文件var一个变量怎么获取到这个变量值_浅析Js中const,let,var的区别及作用域...

    理解:let变量的作用域只能在当前函数中 js中const,let,var的区别及作用域_lianzhang861的博客-CSDN博客​blog.csdn.net 全局作用域中,用 const 和 l ...

  2. js中的堆内存和栈内存

    转自:https://www.cnblogs.com/heioray/p/9487093.html 浅析JS中的堆内存与栈内存 最近跟着组里的大佬面试碰到这么一个问题, Q:说说var.let.con ...

  3. vue中引用js_从JS中的内存管理说起 —— JS中的弱引用

    点击上方"蓝字"关注本公众号 写在前面 在所有的编程语言中,我们声明一个变量时,需要系统为我们分配一块内存.当我们不再需要这个变量时,需要将内存进行回收(这个过程称之为垃圾回收). ...

  4. js堆和栈的区别_几个例子理解不同数据类型的堆栈内存处理

    如有错误烦请指正 js代码的运行环境 浏览器 内核(引擎) node webview(hybrid,嵌入到手机app里面,在app里面运行) ... 下面通过几个例子理解不同数据类型的堆栈内存处理 j ...

  5. python3 urllib 内存泄露_【专家专栏】张昊 | 从urllib2的内存泄露看python的GC

    原标题:[专家专栏]张昊 | 从urllib2的内存泄露看python的GC 惨案回顾 领导:小张啊,安排你个任务,团队需要你做一个功能,提取一批页面上的数据,有问题吗? 小张:当然没问题,您啥时候要 ...

  6. java方法区内存泄露_深入理解java虚拟机-第二章:java内存区域与内存泄露异常...

    2.1概述: java将内存的管理(主要是回收工作),交由jvm管理,确实很省事,但是一点jvm因内存出现问题,排查起来将会很困难,为了能够成为独当一面的大牛呢,自然要了解vm是怎么去使用内存的. 2 ...

  7. linux 内存管理_真香!Linux 原来是这么管理内存的

    这是 Linux 系列第三篇文章,前两篇文章如下 程序员cxuan:初识 Linux 系统,就这一篇了!​zhuanlan.zhihu.com 程序员cxuan:Linux 进程必知必会​zhuanl ...

  8. python变量无需创建和赋值直接使用_学习Python变量,这个笔记就够了

    1.Python中几个概念 1.什么是对象? Python中一切皆对象.对象是Python对数据的抽象.Python程序中所有数据都是由对象或者对象之间的关系表示的(代码也由对象来表示). 每个对象都 ...

  9. java 代码 内存泄露_如何用Java编写一段代码引发内存泄露

    Q:刚才我参加了面试,面试官问我如何写出会发生内存泄露的Java代码.这个问题我一点思路都没有,好囧. A1:通过以下步骤可以很容易产生内存泄露(程序代码不能访问到某些对象,但是它们仍然保存在内存中) ...

最新文章

  1. YOLOv5实现自定义对象训练与OpenVINO部署全解析
  2. Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) C. String Reconstruction 并查集
  3. python Day1作业:用户三次登陆锁定
  4. 从 setNeedsLayout 说起
  5. maven创建的工程eclipse 项目--属性--为什么没有deployment assembly 按钮呢
  6. 公司注销后公章怎么处理,自行保管风险
  7. wcf 接收post数据_简单聊下HTTP中POST和GET请求本质区别
  8. 全面罩防毒面具市场调研
  9. poi解析excel文件(支持xls和xlsx)java学习版
  10. 使用metasploit制作钓鱼网站——browser autopwn攻击
  11. 为程序员准备的英语学习资料
  12. Gdevops广州站:主流数据库的选型、架构设计与迁移实战,一网打尽!
  13. 原生js预览ofd文件,JavaScript
  14. 推荐几个高质量的程序员 B 站视频账号
  15. ES5 to ESNext —  自 2015 以来 JavaScript 新增的所有新特性
  16. 变化环境下渭河流域水文干旱演变特征剖析
  17. 介绍个人计算机水平,计算机个性自我介绍范文
  18. Shell ❀ 条件判断语句
  19. 盟百照相馆影楼摄影工作室选片系统
  20. 齐博cmsv7.0后台getshell

热门文章

  1. WiFi万能钥匙发布iOS4.0新增骚扰电话拦截功能
  2. IT人士运动方式选择建议
  3. 升腾联手VMware 发布首款本土化桌面虚拟化
  4. 用sqlSessionFactoryBeanName而不用sqlSessionFactory的原因
  5. leetcode-654-最大二叉树
  6. CentOS7 systemctl tomcat常用配置
  7. C++ 对象内存布局 (4)
  8. 分数运算C++代码实现
  9. Python学习笔记:Day15 部署Web App
  10. Linux下必须知道的11个网络命令