Эффективность создания обработчика событий в вложенном цикле: создаю ли здесь 1440 функций?
Я создал небольшой код для создания таблицы 24x60. Я хочу напечатать идентификатор каждого <td>
на mouseover
:
<!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>
элементам?
Ответы
Ответ 1
Нет, 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.
Ответ 2
небольшое изменение, находящееся в безопасности:
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 );
}
Ответ 3
Я бы предложил разместить один обработчик событий в таблице и использовать пузырьки событий для обработки в одном месте:
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.
Ответ 4
Да, вы определяете неназванную функцию для каждого элемента там, но вы можете просто определить функцию вне цикла и ссылаться на нее.
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);
}