«Это» - все о сфере видимости. Каждая функция имеет свою собственную область действия, и поскольку все в JS является объектом, даже функция может хранить некоторые значения в себе, используя «это». ООП 101 учит, что «это» применимо только к экземплярам объекта. Поэтому каждый раз, когда выполняет функция, новый «экземпляр» этой функции имеет новое значение «this».
Большинство людей путаются, когда пытаются использовать «это» внутри анонимных функций закрытия например:
(function(value) { this.value = value; $('.some-elements').each(function(elt){ elt.innerHTML = this.value; // uh oh!! possibly undefined }); })(2);
Итак, внутри each (), «this» не содержит «значение», которое вы ожидаете от него (от
this.value = value;над ним). Итак, чтобы справиться с этой проблемой (без каламбуры), разработчик мог:
(function(value) { var self = this; // small change self.value = value; $('.some-elements').each(function(elt){ elt.innerHTML = self.value; // phew!! == 2 }); })(2);
попробовать; вам понравится эта схема программирования
У вас довольно много jQuery-операций, которые, если их собрать во множество строк, могут занимать немалое количество времени. Вместо того, чтобы создавать множество коллекций jQuery (которые имеют некоторые накладные расходы) и пересчитывать индекс, который вы ищете на каждой итерации, рассмотрите использование вместо этого ванильного Javascript, который гораздо более легок. Вы также можете заранее создать массив значений фильтров и связанных с ними индексов, чтобы вам не приходилось перемещаться по DOM, чтобы найти их на каждой итерации:
$(".Filter").on('input', function() {
$(".rowCount").val(filterGrid());
});
function filterGrid() {
const values = Array.from(
document.querySelectorAll('.thead .Filter'),
elm => elm.value
);
let rowsShown = 0;
document.querySelectorAll('.tbody .tr').forEach((tr) => {
const tds = tr.querySelectorAll('.td');
const noMatch = values.some((value, i) => {
if (!value) {
return;
}
const td = tds[i];
return !td.innerHTML.includes(value);
});
if (noMatch) {
tr.style.display = 'none';
} else {
tr.style.display = 'block';
rowsShown++;
}
});
return rowsShown;
}
[ 111] Если этого недостаточно, вы можете использовать циклы for
вместо методов массива, что сделает вещи немного быстрее (хотя и труднее читать).
Если у вас огромное количество строк в .tbody
, и это все еще недостаточно быстро, то вы можете рассмотреть возможность добавления debouncer к слушателю input
, так что filterGrid
вызывается только, скажем, через 200 мс после того, как последний символ был набран, так что большая операция происходит только тогда, когда у вас есть хотя бы бит уверенности, что только что набранный символ может быть последним пользователь хочет ввести (вместо запуска filterGrid
после каждого набранного символа):
let filterTimeout;
$(".Filter").on('input', function() {
clearTimeout(filterTimeout);
filterTimeout = setTimeout(() => {
$(".rowCount").val(filterGrid());
}, 200);
});