执行上下文、调用栈、块级作用域、垃圾回收

2021-03-16  本文已影响0人  李霖弢

执行上下文

一段JS代码在执行之前需要被JavaScript引擎编译。 在编译阶段,变量和函数会被存放到执行上下文中(变量提升),变量的默认值会被设置为undefined。在代码执行阶段,JavaScript引擎会从执行上下文中去查找自定义的变量和函数。

三种创建上下文的场景

内存结构

原始类型的数据值都是直接保存在中的,引用类型的值是存放在中的,防止栈空间内容过多影响上下文切换效率

赋值时,原始类型的赋值会完整复制变量值,而引用类型的赋值是复制引用地址。即上图中d=c指令只是把1003赋值给了d,让d和c指向同一对象

调用栈

JS引擎通过栈管理执行上下文。每当一个上下文被创建,都会被压入栈中。如下脚本中会依次入栈,然后在执行中依次出栈。

var a = 2
function add(b,c){
  return b+c
}
function addAll(b,c){
var d = 10
result = add(b,c)
return  a+result+d
}
addAll(3,6)

通过console.trace()或Chrome开发者工具中打断点后的Call Stack按钮可以查看函数调用关系。

栈溢出(Stack Overflow)

调用栈是有大小的,当无限递归递归次数过大时就会溢出。可以通过循环代替递归的方式解决因递归次数过大时引起的溢出。


垃圾回收

栈回收

栈中的数据随脚本执行,无效内存会被覆盖


堆回收

堆中的数据分为新生区和老生区,两者具有不同的回收策略

全停顿

触发垃圾回收时JS线程会被暂停,通常V8通过增量标记(Incremental Marking)算法将一个完整的回收拆分成多个子任务穿插在其他JS任务中执行,避免卡顿。


块级作用域

通过letconst支持块级作用域,以解决变量提升存在的变量覆盖、变量污染等设计缺陷。
作用块内声明的变量不影响块外面的变量。

let x = 1;
{
  let x = 2;  // 不同的变量
  console.log(x);  // 2
}
console.log(x);  // 1
{
  console.log(myname)//Uncaught ReferenceError: Cannot access 'myname' before initialization
  let myname= '极客邦'
};

上一篇 下一篇

猜你喜欢

热点阅读