이 글은javascript에 대한 관련 지식을 제공합니다. 버튼이 너무 많거나 이벤트 핸들러를 삭제하는 등의 문제를 해결하는 방법을 포함하여 JavaScript의 메모리 및 성능 문제를 주로 소개합니다. 모든 사람에게 도움이 되기를 바랍니다.
관련 권장 사항:javascript 튜토리얼
이벤트 핸들러는 최신 웹 애플리케이션에서 대화형일 수 있기 때문에 많은 개발자가 페이지에서 많은 수의 이벤트 핸들러를 실수로 사용하게 됩니다. 페이지의 이벤트 핸들러 수인 JavaScript는 페이지의 전반적인 성능과 직접적인 관련이 있습니다. 이유는 다양합니다. ① 각 함수는 객체이며 메모리 공간을 차지합니다. 객체가 많을수록 성능이 저하됩니다. ② 특정 이벤트 핸들러에 필요한 DOM 방문 횟수로 인해 전체 지연이 발생합니다. 페이지 상호 작용.
for(let value of values){ ul.innerHTML += '
innerHTML은 각 반복마다 한 번 설정해야 하기 때문에 비효율적입니다. 뿐만 아니라 각 루프마다 innerHTML을 먼저 읽어야 합니다. 하나의 루프 innerHTML에서 두 번 액세스됩니다.
let itemsHtml = "";for(let value of values){ itemsHtml += '
이 수정 후에는 innerHTML에만 값이 할당됩니다.ul.innerHTML = value.map (value => '
ul.innerHTML = values.map(value => '
过多事件处理程序的解决方案是使用事件委托。事件委托利用事件冒泡,可以只使用一个事件处理程序来管理一种类型的事件。例如,click事件冒泡到document。这意味着可以为整个页面指定一个onclick事件处理程序,而不是为每个可点击元素分别指定事件处理程序。
这里包含三个列表项,在被点击时应该执行某个操作,通常的方式是指定三个事件处理程序:
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应用性能不佳都是由于无用的事件处理程序长驻内存导致的。
导致这个问题的原因有两个:
比如通过的DOM方法removeChild()或replaceChild()删除节点。最常见的还是使用innerHTML整体替换页面的某一部分。这时候,被innerHTML删除的元素上如果有事件处理程序,也不会被垃圾收集程序正常清理。
所以,如果在得知某个元素会被删除之前,应手动删除它的事件处理程序,比如btn.onclick = null;//删除事件处理程序
let ps = document.getElementsByTagName("p");for(let i = 0;i
let ps = document.getElementsByTagName("p");for(let i = 0,len=ps.length;i
동일한 코드가 너무 많고 코드가 너무 보기 흉합니다. 이벤트 위임을 사용하면 여러 요소의 공통 조상 노드에 이벤트 핸들러를 추가하기만 하면 문제를 해결할 수 있습니다!let ps = document.getElementsByTagName("p");for(let i = ps.length-1;i>=0;--i){ let p = document.createElement("p"); document.body.appendChild(p);}로그인 후 복사
btn.onclick = null;//Delete event handler
와 같은 해당 이벤트 핸들러를 수동으로 삭제해야 합니다. 이벤트 위임도 이 문제를 해결하는 데 도움이 됩니다. , 요소가 innerHTML로 대체된다는 것을 알고 있는 경우 요소에 이벤트 핸들러를 추가하지 말고 상위 수준 노드에 추가하기만 하면 됩니다. 2. 페이지 언로드로 인해 메모리에 잔여 참조 문제가 발생할 수도 있습니다. 페이지가 언로드된 후 이벤트 핸들러가 정리되지 않으면 여전히 메모리에 남아 있습니다. 그 후에는 브라우저가 페이지를 로드 및 언로드할 때마다(예: 앞으로 이동, 뒤로 이동, 새로 고침 등) 이벤트 핸들러가 재활용되지 않으므로 메모리에 남아 있는 개체 수가 늘어납니다. 일반적으로 페이지가 언로드되기 전에 onunload 이벤트 핸들러에서 모든 이벤트 핸들러를 삭제하는 것이 가장 좋습니다. 이벤트 위임의 장점도 이때 확인할 수 있습니다. 이벤트 핸들러가 적기 때문에 어떤 핸들러를 삭제할지 기억하기 쉽습니다.
let ps = document.getElementsByTagName("p");for(let i = 0;i表达式
let ps = document.getElementsByTagName("p");for(let i = 0,len=ps.length;i表达式①中第一行取得了包含文档中所有
元素的HTMLCollection。因为这个集合是实时的,所以任何时候只要向页面中添加一个新的
元素,再查询这个集合就会多一项。因为浏览器不希望保存每次创建的集合,所以就会在每次访问时更新集合。每次循环都会求值
i ,这意味着要获取所有
元素的查询。因为循环体中创建并向文档中添加一个新的
元素,所以每次循环ps.length的值也会递增。因为两个值都会递增,所以i永远不会等于
ps.length
,因此表达式①会造成死循环。
而表达式②中,又初始化了一个保存集合长度的变量len,因为len保存着循环开始集合的长度,而这个值不会随集合增大动态增长(for循环中初始化变量处只会初始化一次
),所以就可以避免表达式①中出现的无穷循环问题。
如果不想初始化一个变量,也可以使用反向迭代:表达式
let ps = document.getElementsByTagName("p");for(let i = ps.length-1;i>=0;--i){ let p = document.createElement("p"); document.body.appendChild(p);}로그인 후 복사
相关推荐:javascript教程
위 내용은 JavaScript 메모리 및 성능 문제에 대한 깊은 이해의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!