文章目录
前置知识
堆栈
栈
什么是栈
栈其实是一种数据结构,有着先进后出,后进先出
的特性,用生活中的事物来理解最形象的就是汉诺塔了。我们在栈中存储的数据就像汉诺塔的盘子一样,最先放进去在最下面,最后放入的盘子在最上面。我们想拿数据的时候,也需要从塔顶开始拿,也就是最后放入的开始,上面的拿完才能拿下面的。
下图可以看做有三个栈
简而言之,我们可以将栈理解为一个具有先进后出,后进先出
特点的存储空间,对于JavaScript来说,它会把基本数据类型放入栈内存储。
堆
什么是堆
当我们创建一个对象的时候,实际上会在堆空间开辟一个空间,我们声明的变量保存的其实是堆空间的地址
简而言之,堆空间是存放复杂数据类型的存储空间,我们通过变量存储的其实是这些数据在堆空间内的地址。
当我们将一个本来存有地址的变量设置为null时,本质上是将该变量与堆空间的联系斩断,但堆空间内仍存有之前的复杂数据类型。只有当垃圾回收机制执行时,才会将这些没有人引用的复杂数据类型销毁,释放出堆空间。
执行上下文与作用域链
执行上下文
在JavaScript中有三种上下文
-
全局执行上下文:Global Code
JavaScript代码开始运行的默认环境 -
函数执行上下文:Function Code
存在无数个,只有在函数被调用的时候才会被创建,每次调用函数都会创建一个新的执行上下文。 -
Eval 函数执行上下文: 使用eval()执行代码,因为很少用所以本次不做讨论。
在JavaScript代码执行的过程中,默认进入的总是全局执行上下文,JavaScript会把其存入上下文栈中去,每当遇到定义的函数被执行,便会创建一个新的执行上下文,并将其存入上下文栈中去。
当一个函数执行完毕后,上下文栈会将其弹出,将上下文环境交还给上个函数。
作用域链
上下文栈会根据栈内的顺序形成一条作用域链,用来控制变量的访问。处于上层作用域链的函数内部无法访问下层作用域链的变量。
下层作用域链中的函数可以访问上层作用域链的对象,若上层也没有,则再向上查找,直到全局作用域也没有,则返回null。
一、JavaScript中怎么被定义为垃圾
使用局部变量
function makeTrash(){
var a = 1;
}
// 在makeTrash执行时,会创建a这个变量。
// 此时栈空间会为其分配一块区域供其存储。
makeTrash();
// 函数执行完后,由于不再需要变量a,所以此时的a便成为了垃圾
// 栈空间将会释放之前为a分配的空间。
// 至此,垃圾回收完毕
使用对象
// 此时的obj指向堆内存中创建的一块空间
var obj = {
name:'ZhangSan',
age:'18'
}
obj = null
// 当我们对其赋值为null的时候,obj与堆内存中的空间的关系被斩断。
// 由于堆内存中的空间没有人引用,所以这块空间就成了JavaScript中所谓的的垃圾
概括
凡是未被引用的变量或对象,都会被视为垃圾。
可能成为垃圾的特例
全局变量
由于全局对象window的销毁一般发生在页面卸载时,所以对于全局变量是否为垃圾很难进行判断,所以要尽量少用全局变量,或在用完设置