精通JavaScript?关于JavaScript的内存与性能问题,你又了解多少呢?
目录
- 一、何为JavaScript内存与性能
- 二、谈谈关于innerHTML的性能问题?
- 1、使用innerHTML的反面教材
- 2、如何解决
- 三、如何解决类似按钮过多问题?
- 四、事件委托的优点有哪些?
- 五、删除事件处理程序
- 1、删除带有事件处理程序的元素
- 2、页面卸载也会导致内存中残留引用的问题
- 六、如何解决循环中动态添加div,造成的死循环问题?
- 表达式①
- 表达式②
- 表达式③
- 七、JavaScript思维导图
- 八、关注公众号哪吒编程,回复1024,获取Java学习资料,还有不定期的送书活动
一、何为JavaScript内存与性能
因为事件处理程序在现代web应用中可以实现交互,所以很多开发者都会错误地在页面中大量使用它们,在JavaScript中,页面中事件处理程序的数量与页面整体性能直接相关。原因有很多,比如①每个函数都是对象,都要占用内存空间,对象越多,性能越差;②为指定事件处理程序所需访问DOM的次数会先造成整个页面交互的延迟。
二、谈谈关于innerHTML的性能问题?
1、使用innerHTML的反面教材
for(let value of values){ul.innerHTML += '<li>${value}</li>';
}
这段代码效率低,因为每次迭代都要设置一次innerHTML,不仅如此,每次循环都要先读取innerHTML,也就是说一次循环要访问两次innerHTML。
2、如何解决
let itemsHtml = "";
for(let value of values){itemsHtml += '<li>${value}</li>';
}
ul.innerHTML = itemsHtml;
这样修改之后,效率就高多了,只会对innerHTML进行一次赋值,下面代码也可以搞定:
ul.innerHTML = values.map(value => '<li>${value}</li>').join(' ');
三、如何解决类似按钮过多问题?
过多事件处理程序的解决方案是使用事件委托。事件委托利用事件冒泡,可以只使用一个事件处理程序来管理一种类型的事件。例如,click事件冒泡到document。这意味着可以为整个页面指定一个onclick事件处理程序,而不是为每个可点击元素分别指定事件处理程序。
<ul id="myGirls"><li id="girl1">比比东</li><li id="girl2">云韵</li><li id="girl3">美杜莎</li>
</ul>
这里包含三个列表项,在被点击时应该执行某个操作,通常的方式是指定三个事件处理程序:
let item1 = document.getElementById("girl1");
let item2 = document.getElementById("girl2");
let item3 = document.getElementById("girl3");item1.addEventListener("click",(event) => {console.log("我是比比东!");
})item2.addEventListener("click",(event) => {console.log("我是云韵!");
})item3.addEventListener("click",(event) => {console.log("我是美杜莎!");
})
相同代码太多,代码过于丑陋了。
使用事件委托,只要给多有元素的共同的祖先节点添加一个事件处理程序,就可以解决丑陋!
let list = document.getElementById("myGirls");
list.addEventListener("click",(event) => {let target = event.target;switch(target.id){case "girl1":console.log("我是比比东!");break;case "girl2":console.log("我是云韵!");break;case "girl3":console.log("我是美杜莎!");break;}
})
四、事件委托的优点有哪些?
- document对象随时可用,任何时候都可以为它添加一个事件处理程序(不用等待DOMContentLoaded或load事件),通过它处理页面中所有某种类型的事件。这意味着只要页面渲染出可点击的元素,就可以无延迟的起作用。
- 节省花在设置页面事件程序上的事件。
- 减少整个页面所需的内存,提升整体性能。
五、删除事件处理程序
把事件处理程序指定给元素后,在浏览器代码和负责页面交互的JavaScript代码之间就建立了联系。这种联系简历越多,页面性能就越差。除了通过事件委托来限制这种连接之外,还应该及时删除不用的事件处理程序。很多web应用性能不佳都是由于无用的事件处理程序长驻内存导致的。
导致这个问题的原因有两个:
1、删除带有事件处理程序的元素
比如通过的DOM方法removeChild()或replaceChild()删除节点。最常见的还是使用innerHTML整体替换页面的某一部分。这时候,被innerHTML删除的元素上如果有事件处理程序,也不会被垃圾收集程序正常清理。
所以,如果在得知某个元素会被删除之前,应手动删除它的事件处理程序,比如btn.onclick = null;//删除事件处理程序
,事件委托也有助于解决这个问题,如果得知某个元素要被innerHTML替代的时候,就不要给该元素添加事件处理程序了,将其添加到更高层级的节点上即可。
2、页面卸载也会导致内存中残留引用的问题
如果在页面卸载后事件处理程序没有被清理,则它们仍然会残留在内存中。之后,浏览器每次加载和卸载页面(比如通过前进、后退或刷新),内存中残留对象的数量都会增加,这是因为事件处理程序不会被回收。
一般来说,最好在onunload事件处理程序中趁页面尚未卸载先删除所有事件处理程序。这时候也能体现出事件委托的优势,因为事件处理程序少,所以容易记住删除哪些。
六、如何解决循环中动态添加div,造成的死循环问题?
表达式①
let divs = document.getElementsByTagName("div");
for(let i = 0;i<divs.length;++i){let div = document.createElement("div");document.body.appendChild(div);
}
表达式②
let divs = document.getElementsByTagName("div");
for(let i = 0,len=divs.length;i<len;++i){let div = document.createElement("div");document.body.appendChild(div);
}
表达式①中第一行取得了包含文档中所有<div>
元素的HTMLCollection。因为这个集合是实时的,所以任何时候只要向页面中添加一个新的<div>
元素,再查询这个集合就会多一项。因为浏览器不希望保存每次创建的集合,所以就会在每次访问时更新集合。每次循环都会求值i < divs.length
,这意味着要获取所有<div>
元素的查询。因为循环体中创建并向文档中添加一个新的<div>
元素,所以每次循环divs.length的值也会递增。因为两个值都会递增,所以i永远不会等于divs.length
,因此表达式①会造成死循环。
而表达式②中,又初始化了一个保存集合长度的变量len,因为len保存着循环开始集合的长度,而这个值不会随集合增大动态增长(for循环中初始化变量处只会初始化一次
),所以就可以避免表达式①中出现的无穷循环问题。
如果不想初始化一个变量,也可以使用反向迭代:
表达式③
let divs = document.getElementsByTagName("div");
for(let i = divs.length-1;i>=0;--i){let div = document.createElement("div");document.body.appendChild(div);
}
七、JavaScript思维导图
八、关注公众号哪吒编程,回复1024,获取Java学习资料,还有不定期的送书活动
- Java程序设计
- HTML5 APP开发从入门到精通
- Python技术手册
- 区块链开发从入门到精通
精通JavaScript?关于JavaScript的内存与性能问题,你又了解多少呢?相关推荐
- JavaScript 中的内存和性能、模拟事件(读书笔记思维导图)
由于事件处理程序可以为现代 Web 应用程序提供交互能力,因此许多开发人员会不分青红皂白地向页面中添加大量的处理程序.在 JavaScript 中,添加到页面上的事件处理程序数量将直接关系到页面的整体 ...
- JavaScript 事件对内存和性能的影响
程序代码: <%--Created by IntelliJ IDEA.User: 乔克叔叔Date: 2017/12/26Time: 16:45To change this template u ...
- 举例详细说明javascript作用域、闭包原理以及性能问题(转)
转自:http://www.cnblogs.com/mrsunny/archive/2011/11/03/2233978.html 这可能是每一个jser都曾经为之头疼的却又非常经典的问题,关系到内存 ...
- 了解JavaScript中的Memoization以提高性能,再看React的应用
英文: Understanding Memoization in JavaScript to Improve Performance 中文: 了解JavaScript中的Memoization以提高性 ...
- 视频教程-Ajax+jquery从入门到精通2017视频教程-JavaScript
Ajax+jquery从入门到精通2017视频教程 19年软件开发经验,设计开发40多个大型软件,10年从事高等教育,主要为java系列课程,带你轻松进入java生涯. 赖国荣 ¥39.00 立即订阅 ...
- JavaScript中数据在内存中的存储方式
JavaScript中数据在内存中的存储方式 1.js数据类型分类 简单数据类型:Number.String.Boolean.Undefined.Null 复杂数据类型:Object.Array.Fu ...
- 【读书笔记】【WebKit技术内 幕(三)】GPU硬件加速渲染、canvas与WebGL、 JavaScript与JavaScript 引擎、JavaScriptCore与V8
文章目录 前言 Something great 第8章 硬件加速机制 硬件加速基础 -- *** Chromium的硬件加速机制 -- *** 其他硬件加速模块 第9章 JavaScript引擎 Ja ...
- JavaScript(三)—— JavaScript 函数/JavaScript 作用域/JavaScript 预解析/JavaScript 对象
本篇为 JavaScript 系列笔记第三篇,将陆续更新 JavaScript(一)-- 初识JavaScript/注释/输入输出语句/变量/数据类型 JavaScript(二)-- JavaScri ...
- JavaScript——关于JavaScript、在HTML中嵌入JS代码的三种方式、变量
文章目录 JavaScript 01 关于JavaScript 1.1 JS的发展历史 1.2 JS的特性 1.3 JS的组成 1.4 JSP和JS的区别 02 在HTML中嵌入JS代码的三种方式 2 ...
- 服务器多核性能排行,服务器内存多核性能
服务器内存多核性能 内容精选 换一换 本文介绍了弹性云服务器ECS的功能发布和对应的文档动态,新特性将在各个区域(Region)陆续发布,欢迎体验.关于弹性云服务器(ECS)更多历史版本变更内容,请单 ...
最新文章
- 你知道Java的四种引用类型吗?
- 编程控制Word文档中Table的赋值
- 如何创建一个MVC模式的Joomla组件教程(九) 使用数据库下
- 计算机风扇维修,教你简单修理电脑散热风扇
- mx2 android os耗电,魅族MX3 Flyme OS 3.2充电慢、耗电快问题的解决方法详解
- 【转】JMeter学习(二十七)Jmeter常见问题
- xp系统 服务器访问账号,winxp系统下的网站出现访问的用户过多的解决办法
- Linux系统基础(二)
- 使用JavaScript弹出Confirm对话框
- 你了解HTTPS,但你可能不了解X.509
- java判断包含关系contains方法的使用
- Android SwipeRefreshLayout 实现下拉刷新2
- 检测和语义分割_分割和对象检测-第4部分
- win10 中文语言包
- HTML5 Metadata content(文档元数据)
- 0CTF 2016 RSA?(未完成)
- requests使用案例 爬取信用中国
- java实现图片文件上传下载_java实现文件的上传和下载
- mysql从5.7平滑升级到8.0.27
- vb.net 设置桌面壁纸
热门文章
- cad工具箱详细讲解_好用的cad工具箱 易桥CAD工具箱使用教程(附下载)
- C语言数据结构之管道浅析
- 蓝牙MESH学习笔记
- 240万!动漫人脸数据集AnimeCeleb
- 如何在CAD中输入带圈序号?
- 机器学习实战应用案例100篇(十)-蝙蝠算法从原理到实战应用案例
- 微信多开软件苹果版_苹果(iphone)微信双开软件|ios系统福利来了
- lowagie.text 表格带复杂表头 导出word
- 迅雷Chrome插件引发的Uncaught ReferenceError: xl_chrome_menu is not defined
- 智慧社区智能化管理系统搭建