zoukankan      html  css  js  c++  java
  • 常见的 JavaScript 内存泄露

    内存泄漏:由于疏忽或错误造成程序未能释放已经不再使用的内存。内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,导致在释放该段内存之前就失去了对该段内存的控制,从而造成了内存的浪费。

    1、意外的全局变量

    js对未声明变量会在全局最高对象上创建它的引用,(是以属性存在的,而不是变量),如果在游览器上就是window对象,如果在node环境下就是global;如果未声明的变量缓存大量的数据,它可能只有在页面被刷新或者被关闭的时候才会释放内存,这样就造成了内存意外泄漏。如下例子:

    function my() {
        name="my name is tokey"
    }
    my()
    console.log(window)

    在控制台可以看到

    还有通过this创建意外的全局变量

    function my() {
        this.name="my name is tokey"
    }
    my()
    console.log(window.name)  //my name is tokey 此时的this指向的并不是undefined而是全局对象window

    针对上面类型的内存泄漏我们在平时一定要声明变量,不要有全局直接引用。(在JavaScript文件中添加 'use strict',开启严格模式,可以有效地避免上述问题。)

    2、console.log

    作为前端平时使用console.log在控制台打出相对应的信息可以说是非常常见。但如果没有去掉console.log可能会存在内存泄漏。因为在代码运行之后需要在开发工具能查看对象信息,所以传递给console.log的对象是不能被垃圾回收。

    3、闭包

    首先闭包是一个函数A返回一个内联的函数B,及时A函数执行完函数B也可以访问函数A里面的变量,这就是一个简单的闭包。本质上闭包是将函数内部和外部连接起来的一座桥梁。

    function my(name) {
        function sendName() {
            console.log(name)
        }
        return sendName
    }
    var test=my("tokey")
    test()  //tokey

    在my()内部创建的sendName()函数是不会被回收的,因为它被全局变量test引用,处于随时被调用的状态。如果向释放内存可以设置test=null;由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。过度使用闭包可能会导致内存占用过多。

    4、DOM泄漏

    游览器中DOM和js采用的是不一样的引擎,DOM采用的是渲染引擎,而js采用的是v8引擎,所以在用js操作DOM时会比较耗费性能,因为他们需要桥来链接他们。为了减少DOM的操作,我们一般将常用的DOM。我们会采用变量引用的方式会将其缓存在当前环境。如果在进行一些删除、更新操作之后,可能会忘记释放已经缓存的DOM,话不多说直接来个例子

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,initial-scale=1.0, width=device-width">
        <title>Title</title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
    
        </style>
    </head>
    <body>
    <div class="main">
        <div class="test">天</div>
        <div class="item">天</div>
        <div class="item">向</div>
    </div>
    <button id="add">点击我增加</button>
    <button id="remove">点击我减少</button>
    </body>
    <script src="js/Zepto.js"></script>
    <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
    <script>
    var add=document.querySelector("#add");
    var remove=document.querySelector("#remove");
    var main=document.querySelector(".main")
    var test=document.querySelector(".test")
    add.onclick=function () {
        var itemN=document.createElement('div')
        var txt=document.createTextNode('')
        itemN.appendChild(txt)
        main.appendChild(itemN)
    }
    remove.onclick=function () {
        main.removeChild(test)
    }
    </script>
    </html>

    通过chrome游览器的内存调试工作我们可以看到

    在我点击了三次增加之后,可以明显的看到节点(绿线)有三次明显的增加,之后我又删除了一个节点,但绿线没有下降,这是为什么呢?,这也就是内存泄漏。原因就是删除的DOM在js中有全局的引用。也就是我删除的test在文中被引用,所以无法释放内存。所以在删除更新等操作后应该将其设置为null。

    5、被遗忘的timers

    js中常用的定时器setInterval()、setTimeout().他们都是规定延迟一定的时间执行某个代码,而其中setInterval()和链式setTimeout()在使用完之后如果没有手动关闭,会一直存在执行占用内存,所以在不用的时候我们可以通过clearInterval()、clearTimeout() 来关闭其对应的定时器,释放内存。熟悉朋友都知道这类定时器是有误差的,所以游览器给出了专门的API-requestAnimationFrame();大家可以试一下。

  • 相关阅读:
    Arch Linux 安装 ibus-rime
    macOS安装Python MySQLdb
    CentOS 7 安装 gcc 4.1.2
    Windows 10安装Python 2.7和MySQL-python
    小米Air安装Arch Linux之图形界面配置(Gnome 和 sway)持续更新中……
    小米Air 13.3 安装Arch Linux
    Linux Shell脚本攻略总结(1)
    Ubuntu下删除配置错误或者失败的安装包
    oProfile的安装与使用
    动态链接库VS静态链接库
  • 原文地址:https://www.cnblogs.com/yuanzhiguo/p/8056857.html
Copyright © 2011-2022 走看看