Читая одну из
глав https://learn.javascript.ru наткнулся на пример, который вызвал у меня данный вопрос.
Код примера
// ячейка <td> под курсором в данный момент (если есть)
let currentElem = null;
table.onmouseover = function(event) {
// перед тем, как войти на следующий элемент, курсор всегда покидает предыдущий
// если currentElem есть, то мы ещё не ушли с предыдущего <td>,
// это переход внутри - игнорируем такое событие
if (currentElem) return;
let target = event.target.closest('td');
// переход не на <td> - игнорировать
if (!target) return;
// переход на <td>, но вне нашей таблицы (возможно при вложенных таблицах)
// игнорировать
if (!table.contains(target)) return;
// ура, мы зашли на новый <td>
currentElem = target;
target.style.background = 'pink';
};
table.onmouseout = function(event) {
// если мы вне <td>, то игнорируем уход мыши
// это какой-то переход внутри таблицы, но вне <td>,
// например с <tr> на другой <tr>
if (!currentElem) return;
// мы покидаем элемент – но куда? Возможно, на потомка?
let relatedTarget = event.relatedTarget;
while (relatedTarget) {
// поднимаемся по дереву элементов и проверяем – внутри ли мы currentElem или нет
// если да, то это переход внутри элемента – игнорируем
if (relatedTarget == currentElem) return;
relatedTarget = relatedTarget.parentNode;
}
// мы действительно покинули элемент
currentElem.style.background = '';
currentElem = null;
};
Разбирая пример кода, я задумался, почему Илья Кантор не заменил следующую часть кода:
while (relatedTarget) {
if (relatedTarget == currentElem) return;
relatedTarget = relatedTarget.parentNode;
}
На более лаконичную:
if (currentElem.contains(relatedTarget)) return;
По моим рассуждениям, данные коды аналогичны, но так ли это в действительности?
Если коды не аналогичны, то в чём заключается их различие?
Мои рассуждения
Код зависит от relatedTarget и currentElem.
Если relatedTarget равен или является потомком currentElem, то код обработчика прерывается, иначе выполняется
весь код обработчика.
relatedTarget может принимать следующие значения:
- null
- relatedTarget – не потомок currentElem и не равен currentElem
- relatedTarget равен currentElem
- relatedTarget – потомок currentElem