文章目录
如果你去百度这个问题“JavaScript的变量存储机制”,可以看到很多的回答都是:对于原始类型,数据本身是存在栈内,对于对象类型,在栈中存的只是一个堆内地址的引用。
堆栈
可以把堆认为是一个很大的内存存储空间,你可以在里面存储任何类型数据。但是这个空间是私有的,操作系统不会管在里面存储了什么,也不会主动的去清理里面的内容,因此在C语言中需要程序员手动进行内存管理,以免出现内存泄漏,进而影响性能。
但是在一些高级语言 如JAVA会有 垃圾回收(GC) 的概念,用于协助程序管理内存空间,自动清理堆中不再使用的数据。
在栈中存储不了的数据比如对象就会被存储在堆中,在栈中呢是保留了对象在堆中的地址,也就是对象的引用。提到了栈那么接下来我们看下什么是栈?栈是内存中一块用于存储局部变量和函数参数的线性结构,遵循着先进后出的原则。数据只能顺序的入栈,顺序的出栈。当然,栈只是内存中一片连续区域一种形式化的描述,数据入栈和出栈的操作仅仅是栈指针在内存地址上的上下移动而已。如下图所示:
但需要注意的是:内存中栈区的数据,在函数调用结束后,就会自动的出栈,不需要程序进行操作,操作系统会自动回收,也就是:栈中的变量在函数调用结束后,就会消失。 这也正是栈的特点:无需手动管理、轻量、函数调时创建,调用结束则消失。
闭包是什么
红宝书上对于闭包的定义:闭包是指有权访问另外一个函数作用域中的变量的函数。
js中变量类型
局部变量
局部变量:在函数中声明,且在函数返回后不会被其他作用域所使用的对象。下面代码中的 local* 都是局部变量。(scopes是一块堆内存)
function testLocal () {
let local1 = 1;
var local2 = 'str';
const local3 = true;
let local4 = {
a: 1};
}
全局变量
全局变量 ,在浏览器上为 window ,在node 里为 global。全局变量会被默认添加到函数作用域链的最低端,也就是上述函数中 [[Scopes]] 中的最后一个,可以看下上面局部变量例子中 Scopes的最后一个。
全局变量需要特别注意一点:var 和 let/const 的区别。
- var:全局的 var 变量其实仅仅是为 global 对象添加了一条属性。
var testVar = 1;
// 等同于
windows.testVar = 1;
- let / const:全局的 let/const 变量不会修改 window 对象,而是将变量的声明放在了一个特殊的对象下(与 Scope 类似)。
let testLet = 1;
console.dir(() => {
})
被捕获变量
被捕获变量就是局部变量的反面:在函数中声明,但在函数返回后仍有未执行作用域(函数或是类)使用到该变量,那么该变量就是被捕获变量。下面代码中的 catch* 都是被捕获变量。
function