作用域与内存

执行上下文与作用域链

执行上下文决定了变量和函数可以访问哪些数据,以及可以实施哪些行为。每个上下文中都有一个关联的 variable object,而这个上下文中定义的所有变量和函数都存在于这个对象上。

全局上下文是最外层的上下文。根据 ECMAScript 的宿主环境不同,标识全局上下文的对象也可能不同。比如在浏览器中就是常说的 window 对象。

每个函数都有自己的上下文,当代码执行进行函数时,函数的上下文被推到一个上下文栈上。在函数执行完之后,上下文栈会弹出该函数上下文,将控制权返还给之前的执行上下文。

另外还有 eval() 上下文,因为几乎不会使用所以此处不讨论。

上下文的代码在执行的时候,会创建变量对象的一个作用域链。这个作用域链决定了各级上下文中代码在访问变量和函数时的顺序。代码正在执行的上下文的 VO 始终位于作用域链的最前端。

内存管理

JavaScript 运行在一个很特殊的环境,分配给浏览器的内存通常比分配给桌面软件的内存要少很多。这更多的是处于安全考虑而不是别的,就是为了避免运行大量的 JavaScript 的网页耗尽系统资源导致操作系统崩溃。

将内存占用量限制在一个比较小的值可以让网页的性能更好。优化内存占用的最佳手段就是保证在执行代码时只保存必要的数据。如果数据不再必要就把它设置为 null,从而释放它的引用。这个建议尤其适用于全局变量和全局对象的属性。局部变量会在超出作用域之后自动解除引用。不过要注意的是,解除一个值的引用并不会自动导致相关的内存被马上回收,解除引用的关键在于确保相关的值已经不在上下文中了,因此在下次垃圾回收的时候它就会被回收