作者:leee | 来源:互联网 | 2022-02-02 09:47
javascript栏目将讨论另一个重要主题——内存管理,这是由于日常使用的编程语言越来越成熟和复杂,开发人员容易忽视这一问题。我们还将提供一些有关如何处理JavaScript中的内存泄漏的技巧。
Javascript栏目将讨论另一个重要主题,内存管理
编程语言支持不同的内存管理方式。然而,是否使用某一块内存实际上是一个无法确定的问题。换句话说,只有开发人员才能明确一块内存是否可以返回到操作系统。
某些编程语言为开发人员提供了帮助,另一些则期望开发人员能清楚地了解内存何时不再被使用。维基百科上有一些有关人工和自动内存管理的很不错的文章。
四种常见的内存泄漏
1.全局变量
Javascript以一种有趣的方式处理未声明的变量: 对于未声明的变量,会在全局范围中创建一个新的变量来对其进行引用。在浏览器中,全局对象是window。例如:
function foo(arg) {
bar = "some text";
}
等价于:
function foo(arg) {
window.bar = "some text";
}
如果bar在foo函数的作用域内对一个变量进行引用,却忘记使用var来声明它,那么将创建一个意想不到的全局变量。在这个例子中,遗漏一个简单的字符串不会造成太大的危害,但这肯定会很糟。
创建一个意料之外的全局变量的另一种方法是使用this:
function foo() {
this.var1 = "potential accidental global";
}
// Foo自己调用,它指向全局对象(window),而不是未定义。
foo();
可以在Javascript文件的开头通过添加“use strict”来避免这一切,它将开启一个更严格的Javascript解析模式,以防止意外创建全局变量。
尽管我们讨论的是未知的全局变量,但仍然有很多代码充斥着显式的全局变量。根据定义,这些是不可收集的(除非被指定为空或重新分配)。用于临时存储和处理大量信息的全局变量特别令人担忧。如果你必须使用一个全局变量来存储大量数据,那么请确保将其指定为null,或者在完成后将其重新赋值。
2.被遗忘的定时器和回调
以setInterval
为例,因为它在Javascript中经常使用。
var serverData = loadData();
setInterval(function() {
var renderer = document.getElementById('renderer');
if(renderer) {
renderer.innerHTML = JSON.stringify(serverData);
}
}, 5000); //每五秒会执行一次
上面的代码片段演示了使用定时器时引用不再需要的节点或数据。
renderer表示的对象可能会在未来的某个时间点被删除,从而导致内部处理程序中的一整块代码都变得不再需要。但是,由于定时器仍然是活动的,所以,处理程序不能被收集,并且其依赖项也无法被收集。这意味着,存储着大量数据的serverData也不能被收集。
在使用观察者时,您需要确保在使用完它们之后进行显式调用来删除它们(要么不再需要观察者,要么对象将变得不可访问)。
作为开发者时,需要确保在完成它们之后进行显式删除它们(或者对象将无法访问)。
在过去,一些浏览器无法处理这些情况(很好的IE6)。幸运的是,现在大多数现代浏览器会为帮你完成这项工作:一旦观察到的对象变得不可访问,即使忘记删除侦听器,它们也会自动收集观察者处理程序。然而,我们还是应该在对象被处理之前显式地删除这些观察者。例如:
这段代码做了一件事:每次调用replaceThing
的时候,theThing
都会得到一个包含一个大数组和一个新闭包(someMethod)的新对象。同时,变量unuse
d指向一个引用了`originalThing
的闭包。
是不是有点困惑了? 重要的是,一旦具有相同父作用域的多个闭包的作用域被创建,则这个作用域就可以被共享。
在这种情况下,为闭包someMethod
而创建的作用域可以被unused
共享的。unused
内部存在一个对originalThing
的引用。即使unused
从未使用过,someMethod
也可以在replaceThing
的作用域之外(例如在全局范围内)通过theThing
来被调用。
由于someMethod
共享了unused
闭包的作用域,那么unused
引用包含的originalThing
会迫使它保持活动状态(两个闭包之间的整个共享作用域)。这阻止了它被收集。
当这段代码重复运行时,可以观察到内存使用在稳定增长,当GC
运行后,内存使用也不会变小。从本质上说,在运行过程中创建了一个闭包链表(它的根是以变量theThing
的形式存在),并且每个闭包的作用域都间接引用了了一个大数组,这造成了相当大的内存泄漏。
4.脱离DOM的引用
有时,将DOM节点存储在数据结构中可能会很有用。假设你希望快速地更新表中的几行内容,那么你可以在一个字典或数组中保存每个DOM行的引用。这样,同一个DOM元素就存在两个引用:一个在DOM树中,另一个则在字典中。如果在将来的某个时候你决定删除这些行,那么你需要将这两个引用都设置为不可访问。
在引用 DOM 树中的内部节点或叶节点时,还需要考虑另外一个问题。如果在代码中保留对表单元格的引用(
标记),并决定从 DOM 中删除表,同时保留对该特定单元格的引用,那么可能会出现内存泄漏。 你可能认为垃圾收集器将释放除该单元格之外的所有内容。然而,事实并非如此,由于单元格是表的一个子节点,而子节点保存对父节点的引用,所以对表单元格的这个引用将使整个表保持在内存中,所以在移除有被引用的节点时候要移除其子节点。 以上就是介绍Javascript 内存管理+如何处理4个常见的内存泄漏的详细内容,更多请关注其它相关文章!
推荐阅读
-
Itwasworkingcorrectly,butyesterdayitstartedgiving401.IhavetriedwithGooglecontactsAPI ...
[详细]
蜡笔小新 2023-10-15 16:40:16
-
本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ...
[详细]
蜡笔小新 2023-12-14 17:15:38
-
-
本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ...
[详细]
蜡笔小新 2023-12-14 17:15:19
-
本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ...
[详细]
蜡笔小新 2023-12-13 21:23:45
-
本文介绍了使用正则表达式来爬取36Kr网站首页所有新闻的操作步骤和代码示例。通过访问网站、查找关键词、编写代码等步骤,可以获取到网站首页的新闻数据。代码示例使用Python编写,并使用正则表达式来提取所需的数据。详细的操作步骤和代码示例可以参考本文内容。 ...
[详细]
蜡笔小新 2023-12-12 19:16:21
-
本文介绍了前端人员必须知道的三个问题,即前端都做哪些事、前端都需要哪些技术,以及前端的发展阶段。初级阶段包括HTML、CSS、JavaScript和jQuery的基础知识。进阶阶段涵盖了面向对象编程、响应式设计、Ajax、HTML5等新兴技术。高级阶段包括架构基础、模块化开发、预编译和前沿规范等内容。此外,还介绍了一些后端服务,如Node.js。 ...
[详细]
蜡笔小新 2023-12-12 12:45:59
-
本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ...
[详细]
蜡笔小新 2023-12-11 19:55:40
-
在Android中解析Gson解析json数据是很方便快捷的,可以直接将json数据解析成java对象或者集合。使用Gson解析json成对象时,默认将json里对应字段的值解析到java对象里对应字段的属性里面。然而,当我们自己定义的java对象里的属性名与json里的字段名不一样时,我们可以使用@SerializedName注解来将对象里的属性跟json里字段对应值匹配起来。本文介绍了使用@SerializedName注解解析json数据的方法,并给出了具体的使用示例。 ...
[详细]
蜡笔小新 2023-12-11 19:04:09
-
本文介绍了在express工程中如何调用json数据,包括建立app.js文件、创建数据接口以及获取全部数据和typeid为1的数据的方法。 ...
[详细]
蜡笔小新 2023-12-10 13:09:24
-
前言对于从事技术的人员来说ajax是这好东西,都会使用,而且乐于使用。但对于新手,开发一个ajax实例,还有是难度的,必竟对于他们这是新东西。leo开发一个简单的ajax实例,用的是 ...
[详细]
蜡笔小新 2023-10-16 17:08:23
-
表单提交前的最后验证:通常在表单提交前,我们必须确认用户是否都把必须填选的做了,如果没有,就不能被提交到服务器,这里我们用到表单的formname.submit()看演示,其实这个对于我们修炼道 ...
[详细]
蜡笔小新 2023-10-15 18:44:55
-
用JavaScript实现的太空人手表-JS写的太空人手表,没有用canvas、svg。主要用几个大的函数来动态显示时间、天气这些。天气的获取用到了AJAX请求。代码中有详细的注释 ...
[详细]
蜡笔小新 2023-10-13 17:21:38
-
JavaScript在常人看来都是门出不了厅堂的小语言,仅管它没有明星语言的闪耀,但至少网页的闪耀还是需要它的,同时它是一门很实用的语言,本人平时就喜欢拿它来写点实用工具或应用,本文演示用JavaSc ...
[详细]
蜡笔小新 2023-10-13 09:49:41
-
JavaScript概述1.JavaScript定义JavaScript是Netscape公司开发的一种基于对象和事件驱动的脚本语言。它是弱类型语言,只能由浏览器解释执行。其中:脚本语言:解释运行( ...
[详细]
蜡笔小新 2023-10-13 09:36:45
-
JavaScript实现在页面间传值的方法-本文实例讲述了JavaScript实现在页面间传值的方法。分享给大家供大家参考。具体如下:问题如下:在a.html页面中,的 ...
[详细]
蜡笔小新 2023-10-13 01:38:28
-
|