JavaScript变量存储机制
本文分两个部分讨论变量存储模式
- 局部/ 全局/ 闭包变量的存储机制: 在这部分我们讨论什么样的变量有资格存储在栈中
- 不同类型变量的存储机制: 在这部分我们讨论存储在栈中的元素究竟存的是字面量还是引用
先说结论: 万物都存在堆中, 有的变量会在栈上存储引用地址
堆与栈
- 堆是一个很大的内存存储空间, 你可以在里面存储任何类型数据. 操作系统不会自动回收. 在栈中存储不了的数据比如对象就会被存储在堆中, 在栈中呢是保留了对象在堆中的地址, 也就是对象的引用.
- 栈是内存中一块用于存储局部变量和函数参数的线性结构, 遵循着先进后出的原则. 数据只能顺序的入栈, 顺序的出栈. 内存中栈区的数据, 在函数调用结束后, 就会自动的出栈, 不需要程序进行操作, 操作系统会自动回收
于是出现了一个问题, 在闭包出现时, 函数是如何访问到闭包所在的已经销毁的栈中的变量的呢?
局部/全局/闭包变量的存储机制
局部变量: 最简单的, 局部变量存储在作用域所在的栈空间中, 例如
function demo() {let a = 1;let b = '213';let c = [213];let d = new Object(); }console.dir(demo);// ƒ demo() // arguments: null // caller: null // length: 0 // name: "demo" // prototype: // constructor: ƒ demo() // [[Prototype]]: Object // [[FunctionLocation]]: demo.html:53 // [[Prototype]]: ƒ () // [[Scopes]]: Scopes[1] // 0: Global {0: Window, window: Window, self: Window, document: document,
在上面我们找不到定义的变量, 在DevTools的内存-堆分析中也找不到他们
全局变量
使用
var
声明的全局变量
使用var
声明全局变量其实仅仅是为global
对象添加了一条属性, 全局变量会被默认添加到函数作用域链的最底端, 也就是[[Scopes]]
中的最后一个var aaa = 1; // 随便var一个变量 // 等同于 window.aaa = 1; console.dir(()=>{}) // 随便打印一个函数看看他的作用域// anonymous() // length: 0 // name: "" // arguments: (…) // caller: (…) // [[FunctionLocation]]: VM167:1 // [[Prototype]]: ƒ () // [[Scopes]]: Scopes[1] <- 看到函数的作用域 // 0: Global <- 只有global(window)作用域 // aaa: 1 <- 看到window上的aaa // alert: ƒ alert() // atob: ƒ atob() // blur: ƒ blur() // btoa: ƒ btoa()
使用
let
/const
声明全局变量不会修改window
对象, 而是将变量的声明放在了一个特殊的对象Script
下let t1 = 1; const t2 = 2; console.dir(()=>{})// anonymous() // length: 0 // name: "" // arguments: (…) // caller: (…) // [[FunctionLocation]]: VM99:1 // [[Prototype]]: ƒ () // [[Scopes]]: Scopes[2] <- 查看作用域 // 0: Script {t1: 1, t2: 2} <- 看到这些数据被存储到了Script对象中 // 1: Global {window: Window, self: Window, document: document,...}
闭包中的变量: 闭包中的变量会在子函数调用的时候存储为一个对象(存储在堆中), 并在
[[Scopes]]
的Closure(闭包)
中体现function testCatch1 () {let a1 = 1;var a2 = 'a';const a3 = true;let a4 = {a: 1};return function () {console.log(a1, a2, a3, a4)} }function testCatch2 () {let a1 = 1; var a2 = 'a'; const a3 = true; let a4 = {a: 1}; return function () {console.log(a1, a2, a3, a4) } }console.dir(testCatch1())// ƒ anonymous() // arguments: null // caller: null // length: 0 // name: "" // prototype: {constructor: ƒ} // [[FunctionLocation]]: VM469:6 // [[Prototype]]: ƒ () // [[Scopes]]: Scopes[2] // 0: Closure (testCatch1) {a1: 1, a2: 'a', a3: true, a4: {…}} <- 可以看到是按照对象存储在堆中的 // 1: Global {window: Window, self: Window, document: document, name: '',...} <- global在作用域最后console.dir(testCatch2())// ƒ anonymous() // arguments: null // caller: null // length: 0 // name: "" // prototype: {constructor: ƒ} // [[FunctionLocation]]: VM469:16 // [[Prototype]]: ƒ () // [[Scopes]]: Scopes[2] // 0: Closure (testCatch2) {a1: 1, a2: 'a', a3: true, a4: {…}} <- 可以看到是按照对象存储在堆中的, 但是闭包名不同 // 1: Global {window: Window, self: Window, document: document, name: '',}console.dir(testCatch1().a4 === testCatch1().a4)// true <- 连引用对象都是相同的
小结: 除了局部变量, 其他变量都在堆中
那么, 栈中变量是如何存储的呢? 是如开头所说基本数据类型存字面值, 对象存引用地址吗?
不同类型变量的存储机制
- 对于对象类型的数据, 毫无疑问: 栈中存储的是对象在堆中的地址
- 对于基础数据类型呢? 他存储的是字面量吗? 首先我们清楚基础类型包括
- Number & String & Boolean
- Null & Undefined
- Symbol & BigInt
String类型
首先创建两个包含string的对象
const BasicVarGen = function () {this.s1 = 'IAmString'this.s2 = 'IAmString' }let a = new BasicVarGen() let b = new BasicVarGen()
切换到DevTools-内存-堆快照-BasicVarGen
BasicVarGen×2 BasicVarGen@47647__proto__::Object@52873map::system / Map@52877s1::"IAmString"@16065
JavaScript变量存储机制相关推荐
- JavaScript变量提升机制
JavaScript变量提升机制 Js代码执行前(栈内存)还做了一件事那就是变量提升,Js会在所有var function等关键字的提前声明或者定义.. 看以下的代码: console.log(a); ...
- 关于javascript数据存储机制的一个案例。
之前在学习js的结合性的时候,我有点不太明白,在网上找到一个比较经典的C语言优先级结合性的案例,就是下边这一个.本想在js之中测试一番,结果竟然发现得出的结果和网上的不一样,这令我百思不得其解,后经高 ...
- 轻松搞定javascript变量(闭包,预解析机制,变量在内存的分配 )
变量: 存储数据的容器 1.声明 var 2.作用域全局变量. 局部变量. 闭包(相对的全局变量): 3.类型a.基本类型(undefined, null, boolean, numb ...
- js html保存json,如何在json文件中存储jQuery或javascript变量?
我可以知道有没有机会将jquery变量保存在json文件中?提前致谢.如何在json文件中存储jQuery或javascript变量? 我: var image='/test/test.png'; 我 ...
- python变量的存储机制,关于python:python的变量缓存机制
变量的缓存机制 变量的缓存机制(以下内容仅对python3.6.x版本负责) 机制 只有有两个值雷同,就只开拓一个空间 为什么要有这样的机制 在计算机的硬件当中,内存是最重要的配置之一,间接关系到程序 ...
- JavaScript 垃圾回收机制
目录 一.javascript垃圾回收机制 标记清除 引用计数 二.减少JavaScript中的垃圾回收 对象优化 数组优化 函数优化 高级技术 一.javascript垃圾回收机制 解决内存的泄露, ...
- JavaScript 变量
变量是存储信息的容器. 实例 var x=2; var y=3; var z=x+y; 亲自试一试 就像代数那样 x=2 y=3 z=x+y 在代数中,我们使用字母(比如 x)来保存值(比如 2). ...
- javascript变量声明 及作用域
javascript变量声明提升(hoisting) http://openwares.net/js/javascript_declaration_hoisting.html 可能要FQ一下 java ...
- 分布式数据库灵活存储机制与应用实践
2019独角兽企业重金招聘Python工程师标准>>> 嘉宾介绍:郝大为,巨杉数据库技术总监,曾任职IBM DB2数据库部门以及亚信大数据部门,资深的数据库专家.拥有丰富的数据库开发 ...
最新文章
- 分布式系统——zabbix监控tomcat
- wxWidgets:多重继承
- 无法初始化java类_myeclip运行java程序不能初始化类 NoClassDefFoundError
- 任务调度系统 xxl-job,V1.4.1 新特性速览
- python解释器用什么写的_用 Python 从零开始写一个简单的解释器(3)
- 吃鸡电脑配置清单_2020年5月份最佳组装电脑配置清单,吃鸡联盟总有满足你的...
- 06. 当心C++编译器最烦人的分析机制
- nutch batchid
- 愚公移山第一章伪代码
- 甘特图控件VARCHART XGantt:XGantt的用途
- 小学信息技术信息与计算机课件,小学信息技术ppt课件
- 爬虫基本库的使用之正则表达式
- weblogic新建一个managed server并启动
- matplotlib-06 axhline绘制水平/竖直参考线
- 南卫理公会计算机官网,南卫理工会大学
- 常用密码的正则表达式
- 什么叫单稳态,双稳态
- 生活随记 - 念念不忘
- 大学毕业论文如何降低查重率?
- spring启动时只执行一次的方法实现
热门文章
- JavaScript变量提升机制