其实不管什么语言,都有一套垃圾回收机制。为什么要有垃圾回收机制?因为内存,程序运行需要内存,如果没有垃圾回收(循环引用,内存泄漏),那么内存占用就会越来越高,轻点说会影响性能卡顿,严重的直接导致崩溃。

JavaScript使用垃圾回收机制来自动管理内存。

JS的回收机制分两种:1.标记清除 2.引用计数。各大浏览器常用的是前者。

比如,Chrome浏览器限制的所能使用的内存极限(64位为1.4GB,32位为1.0GB),这就意味着浏览器将无法直接操作一些大内存对象。

标记清除:

定义和用法:当变量进入环境时,将变量标记"进入环境",当变量离开环境时,标记为:"离开环境"。某一个时刻,垃圾回收器会过滤掉环境中的变量,以及被环境变量引用的变量,剩下的就是被视为准备回收的变量。

到目前为止,IE、Firefox、Opera、Chrome、Safari的js实现使用的都是标记清除的垃圾回收策略或类似的策略,只不过垃圾收集的时间间隔互不相同。

工作流程:

  1. 垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记。
  2. 去掉环境中的变量以及被环境中的变量引用的变量的标记。
  3. 再被加上标记的会被视为准备删除的变量。
  4. 垃圾回收器完成内存清除工作,销毁那些带标记的值并回收他们所占用的内存空间。

引用计数:

定义和用法:引用计数是跟踪记录每个值被引用的次数。
基本原理:就是变量的引用次数,被引用一次则加1,当这个引用计数为0时,被视为准备回收的对象。
简单点来说就是有没有被引用,没有被引用的就会被回收,比如一个方法里面的变量,运行之后这个方法不再被使用就会被回收。

工作流程:

  1. 声明了一个变量并将一个引用类型的值赋值给这个变量,这个引用类型值的引用次数就是1。
  2. 同一个值又被赋值给另一个变量,这个引用类型值的引用次数加1。
  3. 当包含这个引用类型值的变量又被赋值成另一个值了,那么这个引用类型值的引用次数减1。
  4. 当引用次数变成0时,说明没办法访问这个值了。
  5. 当垃圾收集器下一次运行时,它就会释放引用次数是0的值所占的内存。

但是循环引用的时候就会释放不掉内存。循环引用就是对象A中包含另一个指向对象B的指针,B中也包含一个指向A的引用。
因为IE中的BOM、DOM的实现使用了COM,而COM对象使用的垃圾收集机制是引用计数策略。所以会存在循环引用的问题。
解决:手工断开js对象和DOM之间的链接。赋值为null。IE9把DOM和BOM转换成真正的JS对象了,所以避免了这个问题。

内存泄露的几种情况:

虽然有垃圾回收机制,但是,我们编写代码操作不当还是会造成内存泄漏。

  1. 意外的全局变量引起的内存泄漏。

原因:全局变量,不会被回收。

解决:使用严格模式避免。

  1. 闭包引起的内存泄漏

原因:闭包可以维持函数内局部变量,使其得不到释放。

解决:将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中,删除对dom的引用。

面试题

1)问什么是垃圾

一般来说没有被引用的对象就是垃圾,就是要被清除。 有个例外如果几个对象引用形成一个环,互相引用,但根访问不到它们,这几个对象也是垃圾,也要被清除。

2)如何检垃圾

一种算法是标记 标记-清除 算法。

搞懂闭包JavaScript的GC机制的更多相关文章

  1. 搞懂Dubbo SPI可拓展机制

    前言 阅读本文需要具备java spi的基础,本文不讲java spi,please google it. 一.Dubbo SPI 简介 SPI(Service Provider Interface) ...

  2. 一文搞懂JVM内存结构+GC

    一.jvm是干什么的? 大家都知道java是跨平台语言,一次编译可以在不同操作系统上运行,怎么做到的呢,看下图: javac把写的源代码(java文件),编译成字节码(class文件),字节码部署到l ...

  3. (鸡汤文)这一次我终于搞懂了 JavaScript 定时器的 this 指向!

    开篇语 忽然有一种感觉,每次学习一个知识点就像是谈一场恋爱:从初次邂逅,到彼此了解,一切都那么的符合恋爱的过程! 如果这个知识点再有点"调皮"的话,那简直是让人欲仙欲死而又不可自拔 ...

  4. 来一轮带注释的demo,彻底搞懂javascript中的replace函数

    javascript这门语言一直就像一位带着面纱的美女,总是看不清,摸不透,一直专注服务器端,也从来没有特别重视过,直到最近几年,javascript越来越重要,越来越通用.最近和前端走的比较近,借此 ...

  5. 轻松搞定javascript变量(闭包,预解析机制,变量在内存的分配 )

    变量:  存储数据的容器     1.声明        var   2.作用域       全局变量. 局部变量. 闭包(相对的全局变量):   3.类型         a.基本类型(undefi ...

  6. 彻底搞懂 JS 中 this 机制

    彻底搞懂 JS 中 this 机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.com/jasonGeng88/blog 目录 this 是什么 this 的四种绑定规 ...

  7. 彻底搞懂Javascript的“==”

    本文转载自:@manxisuo的<通过一张简单的图,让你彻底地.永久地搞懂JS的==运算>. 大家知道,==是JavaScript中比较复杂的一个运算符.它的运算规则奇怪,容让人犯错,从而 ...

  8. 让你能看懂的 JavaScript 闭包

    让你能看懂的 JavaScript 闭包 没有废话,直入主题,先看一段代码: var counter = (function() { var x = 1; return function() { re ...

  9. 彻底搞懂JavaScript中的继承

    你应该知道,JavaScript是一门基于原型链的语言,而我们今天的主题 -- "继承"就和"原型链"这一概念息息相关.甚至可以说,所谓的"原型链&q ...

  10. JavaScript彻底搞懂apply和call方法

    彻底搞懂JavaScript中的apply和call方法 call和apply都是为了改变某个函数运行的context上下文而存在的,即为了改变函数体内部this的指向.因为JavaScript的函数 ...

随机推荐

  1. 修改docker容器端口映射

    原文地址 操作步骤如下 关闭docker systemctl stop dokcer 修改配置文件 位置一般是: /var/lib/docker/containers/containerId/host ...

  2. CobaltStrike4.8--云服务器搭建

    系统版本选用 选择最熟悉的版本,我这边用的CentOS7.8,选用乌班图的话,会有一些命令的不一致 配置运行环境 CobaltStrike4.0支持jdk1.8的环境,4.5开始就不支持1.8了,本文 ...

  3. k8s+containerd安装

    准备环境 准备两台服务器节点,如果需要安装虚拟机,可以参考<wmware和centos安装过程> 机器名 IP 角色 CPU 内存 centos01 192.168.109.130 mas ...

  4. IIC、SPI、UART三者对比

    下面将对比三者的各自差异: 参考资料: 1.(112条消息) UART, SPI, IIC的详解及三者的区别和联系_iic spi uart_静思心远的博客-CSDN博客

  5. 2021-7-30 MySql进阶2

    创建临时表只需在table前面加temporary CREATE TEMPORARY TABLE mytable#创建临时表,在断开数据库连接时销毁 ( ID INT NOT NULL, userna ...

  6. tensorflow.js 对视频 / 直播人脸检测和特征点收集

    前言: 这里要介绍的是 Tensorflow.js 官方提供的两个人脸检测模型,分别是 face-detection 和 face-landmarks-detection.他们不但可以对视频中的人间进 ...

  7. TCP四次挥手会经历这么多状态

    TCP三次握手 中讲述了序列号和建立连接,这一篇来说说释放连接. 标志位 TCP首部中在属性标志位,和建立连接.释放连接有关,位于保留和窗口字段中间,其中三个标识与断开连接有关. ACK: ackno ...

  8. TCP如何实现可靠传输、流量控制、拥塞控制

    上一篇文章中讲述了TCP首部的存储的数据,这一篇来聊聊这些数据帮助TCP实现一些特性. 可靠传输 TCP传输会保障数据的可靠和完整,如果数据传输过程丢失了,会重新传输. 保障的第一种协议方式是 停止等 ...

  9. 基于 SharpPcap 开发的简易嗅探器

    Sniffer Based on SharpPcap A packet capture coursework based on sharpcap development 一个基于 SharpPcap ...

  10. CentOS 8 无痕升级到 Rocky Linux

    CentOS 8 无痕升级到 Rocky Linux 1.升级当前系统 dnf upgrade -y 2.重启当前系统: reboot 3.下载脚本: CentOS 8 到 Rocky Linux 8 ...