看完JavaScript高级程序设计第4章一些总结和想法
1.作用域链的的理解
我们都知道函数在运行的时候,函数内部是可以访问在函数外部定义的变量的.这是因为JS中每个函数都有自己的上下文,每个函数在执行的时候,即当前上下文在执行的时候都会生成当前函数内变量对象的作用域链,而这个作用域链的next(我的理解是把作用域链当成链表,通过next属性找到下一个作用域链)指向的就是包含当前函数的上下文.JS需要解析一个变量的时候,会在当前的作用域链看看是否有这个变量,如果没有那就去访问当前作用域链的next(包含当前函数的上下文),看看是否有这个变量,找到就会停止寻找,如果找到全局上下文还没找到,那就会报错.这就是为什么在函数外部定义的变量,而当前函数内部没有定义却能使用的原因.
2.垃圾回收
JS的垃圾回收机制分为两种
标记清除: 这是目前JS最常用的GC策略.标记清除是当变量进入上下文的时候,会被标记为存在上下文的标记,当离开的时候被标记为离开上下文.当GC在运行的时候,会给内存中所以的变量都标记一次,然后在把存在于上下文的变量和其引用的变量去掉标记.剩下的自然就是上下文不会用得的变量,最好GC在把这些不需要用到的变量清理掉.(每个浏览器都有自己的标记方法)
引用计数: 顾名思义,就是记录当前变量被引用的次数,在初始化的时候,变量会被标记为1,每当多一个引用就加1.解除引用就减1.当GC在运行的时候会把标记次数为0的变量给清理掉.但是引用计数有一个问题就是循环引用,可以看下面一段代码
1 2 3 4 5 6
function problem() { let objA = new Object(); let objB = new Object(); objA.otherObj = objB; objB.otherObj = objA; }
这段代码会导致objA和objB的引用次数一直为2,当problem这个函数运行结束后,这两个对象不会被GC给回收掉.如果这个函数被调用很多次,就会导致大量内存不占用,导致内存泄漏.
3.性能优化
出来现在目前一些比较常见的性能优化方法,这一章还写着一些比较底层的性能优化方法.但是由于目前所遇到的场景,这些底层的性能优化对我来说还有点遥远,简单记录下,详情还需要自己去深入研究.
常见的性能优化方法
比较底层的性能优化方法
- 静态内存分配: 比如数组,需要用多少分配多少.
- 隐藏类: V8引擎会做的一个事情.
- 全部变量和全局对象手动解除引用即赋值为null.
- 用const和let替代var,因为var会导致变量提升,而且var没有块级作用域.用let和const可以在块级作用域结束后,GC能尽早回收掉.