不懂JavaScript 内存管理的前端不是好程序员!

简介: 不懂JavaScript 内存管理的前端不是好程序员!

一位客户报告说,当点击一个按钮后,Chrome关闭了该页面,该页面就失去了响应。我最初认为这可能是Chrome扩展的问题。所以,我在隐身模式下进行了测试,但问题也在隐身模式下重现。


在解决这个问题之后,我花了很多时间阅读和理解JavaScript及其编译器。


因此就有了该篇文章


内存泄漏

内存泄漏是因为不需要的内存,但由于某种原因,它没有被回收返回到内存池。


JavaScript的设计方式是,一旦变量被使用,它将自动删除分配的内存,这个过程称为垃圾收集。


JavaScript编译器使用两种不同的垃圾收集器,一种是主Major GC,另一种是Minor GC。


更多: https://v8.dev/blog/trash-talk


Major GC: Major GC从整个堆中收集垃圾。


Minor GC: 小GC收集年轻代的垃圾。


Major GC:

主GC是主垃圾收集器,它识别活对象和死对象,并删除死对象。但是Major GC是在主线程上运行的,所以如果经常调用GC,页面就会变得无响应。


垃圾回收为什么冻结页面?


Garage collector运行在主线路上,所以它会阻塞所有用户输入,因此页面变得无响应。


好吧,但为什么主线程阻塞所有用户输入?


简单的回答是事件循环。更详细的答案,你需要看这个视频。对事件循环和JavaScript编译器有更详细的解释。


更多:https://www.youtube.com/watch?v=8aGhZQkoFbQ


改善应用程序内存管理的通用建议

1. 全局变量

垃圾收集器从不收集全局变量的内存,因此在开始声明全局变量之前,请三思。

但有时,我们会不小心引入了一个全局变量。


请看代码

function foo(arg) { 
  bar = "this is a hidden global variable";
}

您可能会注意到,该变量没有定义但赋值,因此它将成为一个全局变量。

这里,我们泄漏了一个字符串内存,你可能认为这不会产生大问题,但它会覆盖其他一些全局方法,这会引起新的隐患。


2. 引用没法回收

当涉及到对象和数据绑定时,一定要关注内存。

function run(){
  var domObjects = $(".myClass");
  domObjects.click(function(){
    domObjects.addClass(".myOtherClass");
  });
}


一旦函数被调用,JavaScript将删除分配的内存。但是在上面的代码中,GC没有办法收集“domObjects”的内存,因为它绑定到了事件监听器。


如果你想删除这些引用,你可以手动删除它们。

function run(){
  var domObjects = $(".myClass");
  domObjects.click(function(){
    if(domObjects){
      domObjects.addClass(".myOtherClass");
      domObjects = null;
    }
  });
}

3. 字符串连接

这听起来很奇怪,但是字符串连接需要额外的内存。因此,避免字符串连接,而使用模板字面量代替。


33.png


4. 避免创建新对象

新的内存被分配给新的对象、数组等。想办法减少这种情况。


让我们看一个jQuery的例子,


当你从不使用jQuery时,它会增加堆中的内存,所以我们可以避免使用jQuery链接方法。


44.png


6. JSON Parse

当您的应用程序在页面加载期间基于JSON进行渲染时,请考虑使用JSON.stringify和JSON.parse来处理这些数据。

22.png

更多: https://v8.dev/blog/cost-of-javascript-2019#json


7. 避免 try-catch

Try-catch比if分配更多的内存。但是try-catch对于大多数应用程序都是必要的,如果你分析得当,你可以把它们变成try-catch。


11.png

00.png

请看看下面链接中的问题,由node js环境中的try-catch引起的内存泄漏问题。您将获得一些关于try-catch和内存泄漏的知识


https://github.com/nodejs/node/issues/35048


8. 创建新窗口

当创建一个新窗口时,请把废弃的window引用设置为null。


当关闭窗口时,只调用Minor GC,因此只清除年轻代内存块。


如果您想检查JSHeap内存占用情况,请在您的控制台上输入此代码:

memory.usedJSHeapSize

。。.png


9. Callbacks回调

如果事件的回调频率非常高,考虑避免它。让我们以滚动为例。当您将滚动事件绑定到窗口用户向下/向上滚动时,回调调用的频率非常高。


可以使用 Underscore.js 中 _.throttle 和 _.debounce 来减少回调执行,避免页面卡顿。

function log( event ) {
  console.log( $(window).scrollTop(), event.timeStamp );
};
// 控制台记录窗口滚动事件,触发频率比你想象的要快
$(window).scroll( log );
// 控制台记录窗口滚动事件,每250ms最多触发一次
$(window).scroll( _.throttle( log, 250 ) );
function ajax_lookup( event ) {
  // 对输入的内容$(this).val()执行 Ajax 查询
};
// 字符输入的频率比你预想的要快,Ajax 请求来不及回复。
$('input:text').keyup( ajax_lookup );
// 当用户停顿250毫秒以后才开始查找
$('input:text').keyup( _.debounce( ajax_lookup, 250 ) );

更多请阅读https://blog.coding.net/blog/the-difference-between-throttle-and-debounce-in-underscorejs

相关文章
|
25天前
|
JavaScript 前端开发 程序员
前端原生Js批量修改页面元素属性的2个方法
原生 Js 的 getElementsByClassName 和 querySelectorAll 都能获取批量的页面元素,但是它们之间有些细微的差别,稍不注意,就很容易弄错!
|
21天前
|
监控 JavaScript 算法
如何使用内存监控工具来定位和解决Node.js应用中的性能问题?
总之,利用内存监控工具结合代码分析和业务理解,能够逐步定位和解决 Node.js 应用中的性能问题,提高应用的运行效率和稳定性。需要耐心和细致地进行排查和优化,不断提升应用的性能表现。
171 77
|
21天前
|
监控 JavaScript
选择适合自己的Node.js内存监控工具
选择合适的内存监控工具是优化 Node.js 应用内存使用的重要一步,它可以帮助你更好地了解内存状况,及时发现问题并采取措施,提高应用的性能和稳定性。
114 76
|
21天前
|
监控 JavaScript 数据库连接
解读Node.js内存监控工具生成的报告
需要注意的是,不同的内存监控工具可能会有不同的报告格式和内容,具体的解读方法可能会有所差异。因此,在使用具体工具时,还需要参考其相关的文档和说明,以更好地理解和利用报告中的信息。通过深入解读内存监控报告,我们可以不断优化 Node.js 应用的内存使用,提高其性能和稳定性。
100 74
|
23天前
|
存储 缓存 JavaScript
如何优化Node.js应用的内存使用以提高性能?
通过以上多种方法的综合运用,可以有效地优化 Node.js 应用的内存使用,提高性能,提升用户体验。同时,不断关注内存管理的最新技术和最佳实践,持续改进应用的性能表现。
111 62
|
23天前
|
监控 JavaScript Java
Node.js中内存泄漏的检测方法
检测内存泄漏需要综合运用多种方法,并结合实际的应用场景和代码特点进行分析。及时发现和解决内存泄漏问题,可以提高应用的稳定性和性能,避免潜在的风险和故障。同时,不断学习和掌握内存管理的知识,也是有效预防内存泄漏的重要途径。
117 52
|
19天前
|
存储 缓存 监控
如何使用内存监控工具来优化 Node.js 应用的性能
需要注意的是,不同的内存监控工具可能具有不同的功能和特点,在使用时需要根据具体工具的要求和操作指南进行正确使用和分析。
63 31
|
22天前
|
JavaScript 前端开发 Java
springboot解决js前端跨域问题,javascript跨域问题解决
本文介绍了如何在Spring Boot项目中编写Filter过滤器以处理跨域问题,并通过一个示例展示了使用JavaScript进行跨域请求的方法。首先,在Spring Boot应用中添加一个实现了`Filter`接口的类,设置响应头允许所有来源的跨域请求。接着,通过一个简单的HTML页面和jQuery发送AJAX请求到指定URL,验证跨域请求是否成功。文中还提供了请求成功的响应数据样例及请求效果截图。
springboot解决js前端跨域问题,javascript跨域问题解决
|
23天前
|
缓存 监控 JavaScript
避免在Node.js中出现内存泄漏
总之,避免内存泄漏需要在开发过程中保持谨慎和细心,遵循最佳实践,不断优化和改进代码。同时,定期进行内存管理的检查和维护也是非常重要的。通过采取这些措施,可以有效地降低 Node.js 应用中出现内存泄漏的风险,确保应用的稳定和性能。
|
24天前
|
缓存 JavaScript 前端开发
JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用
本文深入讲解了 JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用。
38 5