JavaScript 的全局变量通常不会被垃圾回收,至少在你的网页或 Node.js 进程的整个生命周期内是这样。
这是因为全局变量始终在全局作用域链中,并且只要你的应用程序在运行,这个全局作用域就一直存在。这意味着它们总是可访问的,因此垃圾回收器会认为它们是“被引用”的,也就不会去回收它们。
为什么全局变量难以被回收?
-
持续的可访问性: 全局变量附着在全局对象(在浏览器中是 window,在 Node.js 中是 global)上。只要你的代码在运行,这个全局对象就一直在内存中,所以依附于它的变量也一直处于“活跃”状态。
-
根引用: 垃圾回收器从“根”开始查找所有可达的对象。全局对象就是这些根之一。由于全局变量可以直接通过全局对象访问,它们总是被认为是可达的。
-
内存驻留: 只要页面不关闭,或 Node.js 进程不退出,全局变量就会一直占用内存。
特殊情况和注意事项:
尽管如此,也有一些值得注意的情况:
-
浏览器页面关闭或刷新: 当你关闭一个浏览器标签页或刷新页面时,整个 JavaScript 执行环境都会被销毁,包括所有的全局变量。这时,它们所占用的内存才会被释放。
-
Node.js 进程退出: 类似地,当一个 Node.js 进程被终止时,所有相关的内存(包括全局变量)都会被操作系统回收。
-
显式删除(不推荐): 在某些严格模式不适用的旧环境或特定场景下,你可以尝试使用 delete 操作符来删除全局变量(例如 delete window.myGlobalVar)。但这非常不推荐,因为它可能导致不可预测的行为,并且在现代 JavaScript 代码中几乎不用。
-
间接引用和内存泄漏: 虽然全局变量本身不会被回收,但如果它们引用了大量的对象或数据结构,并且这些对象没有被适当地解除引用,就可能导致内存泄漏。例如,一个全局数组不断地添加新元素而从不删除,即使这些元素在业务逻辑上已经不再需要,它们仍然会因为被全局变量引用而无法被垃圾回收。
结论:
理解这一点很重要,尤其是在开发大型或长时间运行的应用程序时。过度使用全局变量可能会导致不必要的内存占用。最佳实践是限制全局变量的使用,尽可能地使用局部变量、模块作用域或更精细的状态管理模式,以更好地控制内存使用和避免潜在的内存泄漏。