5 питань для підготовки до інтерв'ю по JavaScript. Part 2
03.03.20. Час прочитання - 8 хв
Продовжуємо публікувати питання та відповіді, які допоможуть підготуватися до співбесіди. Першу частину можна знайти у нашому блозі під тегом #front-end.
1. Що таке поширення події (Event Propagation)?
Коли будь-яка подія відбувається в елементі DOM, насправді вона відбувається не тільки в ньому. Подія «поширюється» від об'єкта Window елемента, який його викликав (event.target). При цьому подія послідовно зачіпає всіх предків цільового елемента. Поширення події має три стадії або фази:
- Фаза занурення (захоплення, перехоплення) - подія виникає в об'єкті Window і опускається до цілі події по всіх її предках.
- Цільова фаза - це коли подія досягає цільового елемента.
- Фаза спливання - подія підіймається від event.target, послідовно проходить через всіх його предків і досягає об'єкта Window.
2. Що таке спливання події?
Коли подія відбувається в елементі DOM, вона «спливає» (як бульбашка повітря у воді), переходить від елемента, що викликав подію (event.target), до його батьків, потім підіймається ще вище до наступного елемента, аж поки не досягає об'єкта Window.
Наприклад, є у нас така розмітка:
<div class="grandparent">
<div class="parent">
<div class="child">1</div>
</div>
</div>
І такий JS:
function addEvent(el, event, callback, isCapture = false) {
if (!el || !event || !callback || typeof callback !== 'function') return
if (typeof el === 'string') {
el = document.querySelector(el)
}
el.addEventListener(event, callback, isCapture)
}
addEvent(document, 'DOMContentLoaded', () => {
const child = document.querySelector('.child')
const parent = document.querySelector('.parent')
const grandparent = document.querySelector('.grandparent')
addEvent(child, 'click', function(e) {
console.log('child')
})
addEvent(parent, 'click', function(e) {
console.log('parent')
})
addEvent(grandparent, 'click', function(e) {
console.log('grandparent')
})
addEvent('html', 'click', function(e) {
console.log('html')
})
addEvent(document, 'click', function(e) {
console.log('document')
})
addEvent(window, 'click', function(e) {
console.log('window')
})
})
У методу addEventListener є третій необов'язковий параметр - useCapture. Коли його значення дорівнює false (по дефолту), подія починається з фази спливання. Коли його значення дорівнює true, подія починається з фази занурення. Якщо ми клікнемо по елементу child, в консоль буде виведено: child, parent, grandparent, html, document, window. Ось що таке спливання події.
3. Що таке занурення події?
Як ми вже вище вказували, коли подія відбувається в елементі DOM, вона відбувається не тільки в ньому. У фазі занурення подія опускається від об'єкта Window до мети події через всіх його предків.
Розмітка:
<div class="grandparent">
<div class="parent">
<div class="child">1</div>
</div>
</div>
JavaScript:
function addEvent(el, event, callback, isCapture = false) {
if (!el || !event || !callback || typeof callback !== 'function') return
if (typeof el === 'string') {
el = document.querySelector(el);
}
el.addEventListener(event, callback, isCapture)
}
addEvent(document, 'DOMContentLoaded', () => {
const child = document.querySelector('.child')
const parent = document.querySelector('.parent')
const grandparent = document.querySelector('.grandparent')
addEvent(child, 'click', function(e) {
console.log('child');
}, true)
addEvent(parent, 'click', function(e) {
console.log('parent')
}, true)
addEvent(grandparent, 'click', function(e) {
console.log('grandparent')
}, true)
addEvent('html', 'click', function(e) {
console.log('html')
}, true)
addEvent(document, 'click', function(e) {
console.log('document')
}, true)
addEvent(window, 'click', function(e) {
console.log('window')
}, true)
})
У методу addEventListener є третій необов'язковий параметр - useCapture. Коли його значення дорівнює false (по дефолту), подія починається з фази спливання. Коли його значення дорівнює true, подія починається з фази занурення. Якщо ми клікнемо по елементу child, то побачимо в консолі наступне: window, document, html, grandparent, parent, child. Це і є занурення події.
4. У чому різниця між методами event.preventDefault () і event.stopPropagation ()?
Метод event.preventDefault () відключає поведінку елемента за замовчуванням. Якщо використовувати цей метод в елементі form, то він запобігає надсиланню форми (submit). Якщо використовувати його в contextmenu, то контекстне меню буде відключено (даний метод часто використовується в keydown для перевизначення клавіатури, наприклад, при створенні музичного / відео плеєра або текстового редактора). Метод event.stopPropagation () відключає поширення події (його спливання або занурення).
5. Як дізнатися про використання методу event.preventDefault ()?
Для цього ви можете використовувати властивість event.defaulPrevented, яка повертає логічне значення, що служить індикатором застосування до елементу методу event.preventDefault.