在嵌套循环中创建事件处理程序的效率:我在这里创建了 1440 个函数

Efficiency of creating an event handler in a nested loop: am I creating 1440 functions here?

本文关键字:创建 在这里 1440 函数 效率 嵌套循环 事件处理 程序      更新时间:2023-09-26

我刚刚开发了一点代码来创建24x60表。我想在mouseover上打印每个<td>的 id:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
table {
    background-color:blue;
}
td {
    width: 2px;
    height: 2px;
    background-color:red;
}
</style>
</head>
<body>
<table id="time-table"></table>
<script type="text/javascript">
var table = document.getElementById( "time-table" );
for ( var r = 0; r < 24; r++ ) {
    var row = document.createElement( "tr" );
    for ( var c = 0; c < 60; c++ ) {
        var td = document.createElement( "td" );
        td.id = "td-" + r + "-" + c;
        td.onmouseover = function ( e ) {
            console.log( this.id );
        }
        row.appendChild( td );
    }
    table.appendChild( row );
}
</script>
</body>
</html>

代码有效,但现在我担心它是否经过优化?我是否在嵌套循环中创建 1440 个事件处理函数?或者 JavaScript 解释器是否足够聪明,只创建一个函数并将其分配给 1440 个<td>元素?

不,JavaScript 不会进行任何优化(好吧,也许有些实现可以,但你不应该依赖它(。你真的在创建那么多函数。

最好定义一次函数并重用它:

var handler = function() {
    console.log(this.id);
}
for ( var r = 0; r < 24; r++ ) {
    var row = document.createElement( "tr" );
    for ( var c = 0; c < 60; c++ ) {
        var td = document.createElement( "td" );
        td.id = "td-" + r + "-" + c;
        td.onmouseover = handler;
        row.appendChild( td );
    }
    table.appendChild( row );
}

或者考虑使用事件委托,即将处理程序绑定到单元格的祖先:

table.onmouseover = function(event) {
    event = event || window.event;
    var target = event.target || event.srcElement;
    if(target.nodeName === 'TD') {
        console.log(target.id);
    }
};

这是有效的,因为事件在 DOM 树中冒泡,在某些浏览器中性能方面可能会更好。

了解事件处理的一个很好的资源是 quirksmode.org 的文章。

为了安全起见,这是一个小的更改:

var myFunc = function (e) {
    console.log( this.id );
};
var table = document.getElementById( "time-table" );
for ( var r = 0; r < 24; r++ ) {
    var row = document.createElement( "tr" );
    for ( var c = 0; c < 60; c++ ) {
        var td = document.createElement( "td" );
        td.id = "td-" + r + "-" + c;
        td.onmouseover = myFunc;
        row.appendChild( td );
    }
    table.appendChild( row );
}

我建议将一个事件处理程序放在桌子上,并使用事件冒泡在一个地方处理它:

var table = document.getElementById( "time-table" );
for ( var r = 0; r < 24; r++ ) {
    var row = document.createElement( "tr" );
    for ( var c = 0; c < 60; c++ ) {
        var td = document.createElement( "td" );
        td.id = "td-" + r + "-" + c;
        row.appendChild( td );
    }
    table.appendChild( row );
}
table.addEventListener('mouseover', function(e) {
    console.log(e.target.id);
}, false);

对于旧版本的 IE,您将使用 attachEvent 而不是 addEventListener。

是的,你为那里的每个元素定义了一个未命名的函数,但你可以简单地在循环之外定义函数并引用它。

var printMyId = function(e) {
  console.log(e.srcElement.id);
};
var table = document.getElementById("time-table");
for (var r = 0; r < 24; r++) {
  var row = document.createElement("tr");
  for (var c = 0; c < 60; c++) {
    var td = document.createElement("td");
    td.id = "td-" + r + "-" + c;
    td.onmouseover = printMyId;
    row.appendChild(td);
  }
  table.appendChild(row);
}