You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
function func3 () {
const a = 1
const b = 2
// 函数执行时,a b 分别被标记 进入环境
}
func3() // 函数执行结束,a b 被标记 离开环境,被回收
2、引用计数
统计引用类型的变量声明后被引用的次数,当次数为0时,该变量将被回收。
function func4 () {
const c = {} // 引用类型变量 c的引用计数为 0
let d = c // c 被 d 引用 c的引用计数为 1
let e = c // c 被 e 引用 c的引用计数为 2
d = {} // d 不再引用c c的引用计数减为 1
e = null // e 不再引用 c c的引用计数减为 0 将被回收
}
但是引用计数的方式,有一个相对明显的缺点——循环引用,如下demo:
function func5 () {
let f = {}
let g = {}
f.prop = g
g.prop = f
// 由于 f 和 g 互相引用,计数永远不可能为 0
}
垃圾回收机制
概念
垃圾回收机制,是指执行环境找到内存中不再使用的变量,然后释放其占有的内存空间。JavaScript、Java、python语言具有自动垃圾回收机制,而C和C++之类的语言,开发人员需手工跟踪内存的使用情况,定时清扫内存垃圾。
垃圾回收2种策略
1、标记清除
当变量进入执行环境时,标记进入环境”,当变量离开执行环境时则标记为“离开环境”,被标记为“进入环境”的变量是不能被回收的,因为它们正在被使用,而标记为“离开环境”的变量则可以被回收。
2、引用计数
统计引用类型的变量声明后被引用的次数,当次数为0时,该变量将被回收。
但是引用计数的方式,有一个相对明显的缺点——循环引用,如下demo:
像循环引用的情况,需要手动将变量进行内存释放:
内存泄露
概念
内存泄露(Memory Leak),是指程序已动态分配的堆内存由于某种原因未释放或无法释放,造成系统的内存浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。
4类内存泄露及如何避免
1、意外生成全局变量
未用var声明创建的变量bar意外挂在了window全局,全局变量只有当页面被关闭才会被销毁。这种写法会造成内存泄露。
为了避免此类内存泄露,可以在js文件头部添加
'use strict'
,启用严格模式解析JavaScript。2、未销毁定时器和回调函数
如果后续 oHtml 元素被移除, 整个定时器实际上没有任何作用. 但如果你没有回收定时器, 整个定时器依然有效, 不但定时器无法被内存回收, 定时器函数中的依赖也无法回收. 在这个案例中的 fn 也无法被回收。
如果oHtml 元素被移除,可以清除定时器,避免内存泄露。
3、DOM的引用
上述案例中, 即使我们对于 test 元素进行了移除, 但是仍然有对 test 元素的引用, 依然无法对齐进行内存回收。再举个例子: 如果我们引用了一个表格中的 td 元素, 一旦在 Dom 中删除了整个表格, 我们直观的觉得内存回收应该回收除了被引用的 td 外的其他元素。 但是事实上, 这个 td 元素是整个表格的一个子元素, 并保留对于其父元素的引用。这就会导致对于整个表格, 都无法进行内存回收。
为了避免这类内存泄露,我们需谨慎使用DOM引用。
4、闭包
js闭包中,内部函数有权访问其外部函数中的变量,闭包的变量经常被循环引用,就不会进行垃圾回收,有可能会造成内存泄露。
我们需谨慎使用闭包,来避免内存泄露。
The text was updated successfully, but these errors were encountered: