javascript 匿名事件与命名事件
javascript anonymous events vs named
我正在处理一些需要将一系列事件附加到动态创建的元素的代码。我想知道在内存泄漏方面是否有一种方法比另一种方法更好。我花了几个小时研究 Chome 的内存配置文件,但我终其一生都无法弄清楚如何使用它,所以我无法判断是否有一种方法会造成泄漏。
在从 DOM 中删除节点之前,我以两种方式分离了 onclick
事件,但不确定是否还有其他我需要注意的事情。
我在下面创建了一个示例。
click me 1
创建一个新的 div 并将命名函数分配给第一个和第二个 onclick
click me 2
创建一个新的 div 并将匿名内部函数分配给第一个和第二个 onclick
function startIt1(div)
{
var newDiv = document.createElement("div");
newDiv.className = "two";
newDiv.innerText = "click me 1a";
newDiv.onclick = step1;
document.body.appendChild(newDiv);
}
function step1()
{
this.innerText = "click me 1b";
this.className = "three";
this.onclick = step2;
}
function step2()
{
this.onclick = null;
this.parentNode.removeChild(this);
}
function startIt2(div)
{
var newDiv = document.createElement("div");
newDiv.className = "two";
newDiv.innerText = "click me 2a";
newDiv.onclick = function()
{
newDiv.innerText = "click me 2b";
newDiv.className = "three";
newDiv.onclick = function()
{
newDiv.onclick = null;
newDiv.parentNode.removeChild(newDiv);
}
};
document.body.appendChild(newDiv);
}
div
{
padding: 20px;
margin: 20px;
}
.one
{
background-color: lime;
}
.two
{
background-color: yellow;
}
.three
{
background-color: cyan;
}
}
<div class="one" onclick="startIt1(this)">click me 1</div>
<div class="one" onclick="startIt2(this)">click me 2</div>
除非有一些您没有显示的东西持有对那些事件处理程序的引用,否则在处理程序被删除后,以上都不会不必要地保留内存。
第二个,使用内部函数,理论上保持调用 startIt2
的上下文(它是一个抽象对象)直到处理程序和元素被删除,但仅在此之前。那是因为内部函数是该上下文的闭包。一个聪明的 JavaScript 引擎可以稍微优化它,但不能完全删除它,因为内部函数在其中引用了 newDiv
。 (如果您改用 this
,智能引擎将能够完全优化上下文保留——它是否 会 取决于引擎以及它是否是代码中的热点.)
可能有点离题,但是使用命名函数有与内存消耗无关的好处,例如在调用堆栈中有意义的名称等等......当然,如果你在多个地方使用同一个处理程序,你可以使用一种功能而不是多种功能。
我正在处理一些需要将一系列事件附加到动态创建的元素的代码。我想知道在内存泄漏方面是否有一种方法比另一种方法更好。我花了几个小时研究 Chome 的内存配置文件,但我终其一生都无法弄清楚如何使用它,所以我无法判断是否有一种方法会造成泄漏。
在从 DOM 中删除节点之前,我以两种方式分离了 onclick
事件,但不确定是否还有其他我需要注意的事情。
我在下面创建了一个示例。
click me 1
创建一个新的 div 并将命名函数分配给第一个和第二个onclick
click me 2
创建一个新的 div 并将匿名内部函数分配给第一个和第二个onclick
function startIt1(div)
{
var newDiv = document.createElement("div");
newDiv.className = "two";
newDiv.innerText = "click me 1a";
newDiv.onclick = step1;
document.body.appendChild(newDiv);
}
function step1()
{
this.innerText = "click me 1b";
this.className = "three";
this.onclick = step2;
}
function step2()
{
this.onclick = null;
this.parentNode.removeChild(this);
}
function startIt2(div)
{
var newDiv = document.createElement("div");
newDiv.className = "two";
newDiv.innerText = "click me 2a";
newDiv.onclick = function()
{
newDiv.innerText = "click me 2b";
newDiv.className = "three";
newDiv.onclick = function()
{
newDiv.onclick = null;
newDiv.parentNode.removeChild(newDiv);
}
};
document.body.appendChild(newDiv);
}
div
{
padding: 20px;
margin: 20px;
}
.one
{
background-color: lime;
}
.two
{
background-color: yellow;
}
.three
{
background-color: cyan;
}
}
<div class="one" onclick="startIt1(this)">click me 1</div>
<div class="one" onclick="startIt2(this)">click me 2</div>
除非有一些您没有显示的东西持有对那些事件处理程序的引用,否则在处理程序被删除后,以上都不会不必要地保留内存。
第二个,使用内部函数,理论上保持调用 startIt2
的上下文(它是一个抽象对象)直到处理程序和元素被删除,但仅在此之前。那是因为内部函数是该上下文的闭包。一个聪明的 JavaScript 引擎可以稍微优化它,但不能完全删除它,因为内部函数在其中引用了 newDiv
。 (如果您改用 this
,智能引擎将能够完全优化上下文保留——它是否 会 取决于引擎以及它是否是代码中的热点.)
可能有点离题,但是使用命名函数有与内存消耗无关的好处,例如在调用堆栈中有意义的名称等等......当然,如果你在多个地方使用同一个处理程序,你可以使用一种功能而不是多种功能。