更新:谢谢你们的支持,最近折腾了一个博客官网出来,方便你们系统阅读,后续会有更多内容和更多优化,猛戳这里查看javascript
------ 如下是正文 ------前端
本期的主题是调用堆栈,本计划一共28期,每期重点攻克一个面试重难点,若是你还不了解本进阶计划,文末点击查看所有文章。java
若是以为本系列不错,欢迎点赞、评论、转发,您的支持就是我坚持的最大动力。webpack
堆栈的内容和执行顺序我就不说了,前面两篇已经介绍过了。git
可是今天补充一个知识点:某些状况下,调用堆栈中函数调用的数量超出了调用堆栈的实际大小,浏览器会抛出一个错误终止运行。github
对于下面的递归就会无限制的执行下去,直到超出调用堆栈的实际大小,这个是浏览器定义的。web
function foo() {
foo();
}
foo();
复制代码
如今正式开始今天的主题,内存空间详解面试
栈的结构就是后进先出**(LIFO)**,若是读过前面两篇文章应该是至关熟悉了。文中使用乒乓球盒子的结构来解释。算法
处于盒子中最顶层的乒乓球5,它必定是最后被放进去,但能够最早被使用。而咱们想要使用底层的乒乓球1,就必须将上面的4个乒乓球取出来,让乒乓球1处于盒子顶层。跨域
堆数据结构是一种树状结构。它的存取数据的方式与书架和书很是类似。咱们只须要知道书的名字就能够直接取出书了,并不须要把上面的书取出来。JSON格式的数据中,咱们存储的key-value
能够是无序的,由于顺序的不一样并不影响咱们的使用,咱们只须要关心书的名字。
队列是一种先进先出(FIFO)的数据结构,这是事件循环(Event Loop)的基础结构,事件循环咱们会在第8期详解介绍。
首先咱们应该知道内存中有栈和堆,那么变量应该存放在哪里呢,堆?栈?
在计算机的数据结构中,栈比堆的运算速度快,Object是一个复杂的结构且能够扩展:数组可扩充,对象可添加属性,均可以增删改查。将他们放在堆中是为了避免影响栈的效率。而是经过引用的方式查找到堆中的实际对象再进行操做。因此查找引用类型值的时候先去栈查找再去堆查找。
问题1:
var a = 20;
var b = a;
b = 30;
// 这时a的值是多少?
复制代码
问题2:
var a = { name: '前端开发' }
var b = a;
b.name = '进阶';
// 这时a.name的值是多少
复制代码
问题3:
var a = { name: '前端开发' }
var b = a;
a = null;
// 这时b的值是多少
复制代码
如今来解答一下,三个问题的答案分别是20
、‘进阶’
、{ name: '前端开发' }
b.name
的值后,相应的a.name
也就发生了改变。null
是基本类型,a = null
以后只是把a存储在栈内存中地址改变成了基本类型null,并不会影响堆内存中的对象,因此b的值不受影响。JavaScript的内存生命周期是
JavaScript有自动垃圾收集机制,最经常使用的是经过标记清除的算法来找到哪些对象是再也不继续使用的,使用a = null
其实仅仅只是作了一个释放引用的操做,让 a 本来对应的值失去引用,脱离执行环境,这个值会在下一次垃圾收集器执行操做时被找到并释放。
在局部做用域中,当函数执行完毕,局部变量也就没有存在的必要了,所以垃圾收集器很容易作出判断并回收。可是全局变量何时须要自动释放内存空间则很难判断,所以在开发中,须要尽可能避免使用全局变量。
var a = {n: 1};
var b = a;
a.x = a = {n: 2};
a.x // 这时 a.x 的值是多少
b.x // 这时 b.x 的值是多少
复制代码
进阶系列文章汇总:github.com/yygmind/blo…,内有优质前端资料,以为不错点个star。
我是木易杨,网易高级前端工程师,跟着我每周重点攻克一个前端面试重难点。接下来让我带你走进高级前端的世界,在进阶的路上,共勉!