JS执行流程
详细过程
全局代码的执行
1.解析代码:
栈中:先会创建一个执行上下文Excution context(EC). 在EC中,有一个Variable Object,与堆中:Global Object(GO)相绑定.
Global Object中就是window对象,里面放着一些Math,Date,Number.和var变量,代码中所写的var变量,函数等等都是GO的属性,在解析阶段这些值都是undefinied.如果有函数,会立刻创建一个函数的对象Function Object,并且Function Object中包含基本的属性length name.GO中这个函数属性就指向这个Function Object. 如果这个函数是多层嵌套,只会有最外层的函数不会继续向内解析内层函数.
2.执行时
var变量会被依次赋值. 执行到函数时,栈中会创建一个新的EC,堆中会创建一个(Activation object)AO对象, 并且这个EC的VO会与这个AO对象相绑定,会使用arguments作为初始化.
作用域链只跟函数声明的位置有关,和执行的位置无关.
内存管理
垃圾回收Garbage Collection (GC)
Reference Counting 引用计数
当一个对象有一个引用指向它时,那么这个对象的引用retainCount就+1
对象的引用为0时,这个对象就可以被销毁掉
弊端可能会产生循环引用
mark-Sweep 标记清除
核心思路是可达性Reachability
设置一个根对象root object,垃圾回收期会定期从这个根开始,找所有从根开始有引用到的对象,对于哪些没有引用到的对象,就认为是不可用的对象
这个算法可以很好的解决循环引用的问题
Mark-Compact
回收期间会将保留的存储对象搬运到连续的内存空间,从而整合空闲空间,避免内存碎片化
Generational collection
对象会分为两组,新的和旧的
许多对象的出现,完成它们的工作并很快死去,它们可以很快被清理
那些长期存活的对象会变得老旧,而且被检查的频次也会减少
Incremental collection
如果有许多对象,并且我们试图依次遍历并标记整个对象集,则可能需要一些时间,并在执行过程中带来明显的延长.
所以引擎试图将辣椒手机工作分层几部分来做然后将这几部分会逐一进行处理,这样会有许多微小的延迟而不是一个大的延迟
Idle-time collection闲时收集
垃圾收集器只会在CPU空闲时尝试运行,以减少可能对代码执行的影响
闭包Closure
闭包实现上是一个结构体,它存储了一个函数和一个关联的环境.
广义上,JS中的函数都是闭包
狭义上,JS中一个函数,如果访问了外层作用域的变量,那么它是一个闭包