Open yygmind opened 5 years ago
a.x = a = {n: 2};
是a 还保存着对{n:1}的引用, 然后再改变引用到 {n:2}吗? 为什么啊?
理解了。 a.x 是已经先指向原对象了。 然后在赋值。
先提个错别字哦
a.x = a = {n:2} 执行顺序 a.x -> a = {n:2} -> (a.x)= a (.运算符优先级大于=) a.x 在最开始就已经执行 类似 temp = a.x ; temp = a = {n:2} 注:javascript 执行顺序从右往左的
从右往左
最后a={n:2},b={n=1,x:{n:2}}
点运算优先级最高
关键点在于对象的引用和点运算符的优先级
a.x = undefined b.x = {n:2}
个人理解:取属性的运算符优先级最高,赋值运算符是右结合性的。 因此执行顺序是 1). 先取出a.x 2). a = {x: 2}, 3). a.x = a 运行第一步时,a还保留有b的引用,因此第三步就相当于b.x = {x: 2} 如有错误请指正
转一篇针对思考题的文章 http://www.cnblogs.com/vajoy/p/3703859.html
a.x = {n: 2}; b = {n: 1}; b.x = undefined;
原文 - “将他们放在堆中是为了不影响栈的效率。而是通过引用的方式查找到堆中的实际对象再进行操作。” 前面的是 ‘是’ 还是 ‘不是’ ?
https://www.zhihu.com/question/41220520 看了这个你还不懂的话,你来找我
先执行‘.’,于是a.x = a = {n: 2}可以理解成({ n: 1 }).x = a = { n:2 }
循环调用栈溢出,我的浏览器报错是Uncaught RangeError: Maximum call stack size exceeded
这个网站可以查看执行过程 看了再结合
a.x = a = {n:2} 执行顺序 a.x -> a = {n:2} -> (a.x)= a (.运算符优先级大于=) a.x 在最开始就已经执行 类似 temp = a.x ; temp = a = {n:2} 注:javascript 执行顺序从右往左的
.优先级大于赋值 a.x先声明 随后赋值右到左 a={n:2}返回{n:2}此时内存中b.x指向{n:2}
没必要在这里提堆数据结构,堆栈的堆和数据结构的堆是两回事
原文中:基本类型 --> 保存在栈内存中。callstack frame 一旦 pop up 掉,请问闭包去哪里找数据? P.S. 本文的引子是 callstack, 后面是数据结构... 容易误解
本期的主题是调用堆栈,本计划一共28期,每期重点攻克一个面试重难点,如果你还不了解本进阶计划,文末点击查看全部文章。
如果觉得本系列不错,欢迎点赞、评论、转发,您的支持就是我坚持的最大动力。
堆栈的内容和执行顺序我就不说了,前面两篇已经介绍过了。
但是今天补充一个知识点:某些情况下,调用堆栈中函数调用的数量超出了调用堆栈的实际大小,浏览器会抛出一个错误终止运行。
对于下面的递归就会无限制的执行下去,直到超出调用堆栈的实际大小,这个是浏览器定义的。
现在正式开始今天的主题,内存空间详解
栈数据结构
栈的结构就是后进先出(LIFO),如果读过前面两篇文章应该是相当熟悉了。文中使用乒乓球盒子的结构来解释。
处于盒子中最顶层的乒乓球5,它一定是最后被放进去,但可以最先被使用。而我们想要使用底层的乒乓球1,就必须将上面的4个乒乓球取出来,让乒乓球1处于盒子顶层。
堆数据结构
堆数据结构是一种树状结构。它的存取数据的方式与书架和书非常相似。我们只需要知道书的名字就可以直接取出书了,并不需要把上面的书取出来。JSON格式的数据中,我们存储的
key-value
可以是无序的,因为顺序的不同并不影响我们的使用,我们只需要关心书的名字。队列
队列是一种先进先出(FIFO)的数据结构,这是事件循环(Event Loop)的基础结构,事件循环我们会在第8期详解介绍。
变量的存放
首先我们应该知道内存中有栈和堆,那么变量应该存放在哪里呢,堆?栈?
在计算机的数据结构中,栈比堆的运算速度快,Object是一个复杂的结构且可以扩展:数组可扩充,对象可添加属性,都可以增删改查。将他们放在堆中是为了不影响栈的效率。而是通过引用的方式查找到堆中的实际对象再进行操作。所以查找引用类型值的时候先去栈查找再去堆查找。
几个问题
问题1:
问题2:
问题3:
现在来解答一下,三个问题的答案分别是
20
、‘进阶’
、{ name: '前端开发' }
b.name
的值后,相应的a.name
也就发生了改变。null
是基本类型,a = null
之后只是把a存储在栈内存中地址改变成了基本类型null,并不会影响堆内存中的对象,所以b的值不受影响。内存空间管理
JavaScript的内存生命周期是
JavaScript有自动垃圾收集机制,最常用的是通过标记清除的算法来找到哪些对象是不再继续使用的,使用
a = null
其实仅仅只是做了一个释放引用的操作,让 a 原本对应的值失去引用,脱离执行环境,这个值会在下一次垃圾收集器执行操作时被找到并释放。在局部作用域中,当函数执行完毕,局部变量也就没有存在的必要了,因此垃圾收集器很容易做出判断并回收。但是全局变量什么时候需要自动释放内存空间则很难判断,因此在开发中,需要尽量避免使用全局变量。
思考题
参考
进阶系列目录
交流
进阶系列文章汇总:https://github.com/yygmind/blog,内有优质前端资料,觉得不错点个star。
我是木易杨,网易高级前端工程师,跟着我每周重点攻克一个前端面试重难点。接下来让我带你走进高级前端的世界,在进阶的路上,共勉!