event-driven programming : 프로그램의 흐름을 이벤트 중심으로 제어하는 프로그래밍 방식
사용자와의 상호작용에 따라 (버틀 클릭, 키보드 입력, 마우스 이동 등) 함수를 호출하여 어떤 처리를 하고 싶을 때, 보통 사용자가 행동을 "언제" 할지 몰라서 함수를 "언제" 호출해야되는지 알 수 없다.
하지만 다행히도 브라우저는 이런 특정 사건을 감지하여 이벤트 event를 발생시킬 수 있기에 해당하는 타입의 이벤트가 발생했을 때 호출될 함수(이벤트 핸들러)를 브라우저에게 알려 호출을 위임(이벤트 핸들러 등록)한다.
* on이벤트타입 = 함수 호출문 (사실 함수 몸체 자체를 의미함)
<body>
<button onclick="handleClick">Click</button>
<script>
function handleClick(){
console.log(1)
}
</script>
</body>
-> 이벤트 핸들러에 인수를 전달하기 위해 함수 참조문이 아닌 함수 호출문을 전달하게 된다.
결국 DOM 노드 객체의 이벤트 핸들러 프로퍼티로 변환되므로 결과적으로 이벤트 핸들러 프로퍼티 방식과 동일하다고 볼 수 있다.
관심사 분리 측면에서 더이상 사용하지 않는 것이 좋지만 CBD(Component Based Development) 방식의 Angular/React/Svelte/Vue.js 같은 프레임워크/라이브러리에서는 이 방식으로 처리한다. CBD에서는 HTML, CSS, JS를 관심사가 다른 개별적인 요소로 보지 않고, 뷰를 구성하기 위한 구성요소로 보기 때문에 관심사가 다르다고 생각하지 않는다.
* 이벤트타깃. on이벤트타입 = 이벤트 핸들러 (함수)
<body>
<button>click</button>
<script>
const $button = document.querySelector('button');
$button.onclick = function (){console.log(1)}; <- 다음 핸들러에 의해 재할당되었기 때문에 이 부분은 실행되지 않는다.
$button.onclick = function (){console.log(2)};
$button.onclick = null; <- 이벤트 핸들러 제거
</script>
</body>
* 이벤트타깃.addEventListener(이벤트타입, 이벤트핸들러[, capture 사용여부])
<body>
<button>click</button>
<script>
const $button = document.querySelector('button');
$button.addListener('click',function(){console.log(1)}, true)
$button.addListener('click',function(){console.log(2)}, true)
$button.removeListener('click',function(){console.log(1)},false) //마지막 매개변수 다름->실패
$button.removeListener('click',()=>console.log(1),true) //무명 핸들러->실패
$button.removeListener('click',function(){console.log(1)}, true) //제거 성공
</script>
</body>
<body>
<p>이벤트 <button>버튼</button></p>
<script>
document.body.addEventListener('click',()=>{console.log('버블링')}) - (3)
document.querySelector('p').addEventListener('click',()=>{console.log('캡쳐링')}) - (1)
document.querySelector('button').addEventListener('click',()=>{console.log('타겟')}) - (2)
</body>
//console.log 결과
캡처링
타겟
버블링
<style>
#fruits {
display: flex;
list-style-type: none;
padding: 0;
}
#fruits .active {
color:red;
text-decoration:underline;
}
</style>
<body>
<nav>
<ul id="fruits">
<li id ="apple" class="active">Apple</li>
<li id ="banana">Banana</li>
<li id ="orange">Orange</li>
</ul>
</nav>
...
<script>
...
//위임 전
document.getElementById('apple').onclick=activate;
document.getElementById('banana').onclick=activate;
document.getElementById('orange').onclick=activate;
//위임 후 (1)
$fruits.onclick = activate;
</script>
</body>
e.preventDefault();
e.stopPropagation();
DOM 이벤트를 제어하는 방법
사용 이유 : 사용자가 스크롤과 같은 수많은 이벤트를 발생시켰을 때 이에 대한 무수한 callback이 발생하고, 이는 큰 리소스 소모로 이어짐. 이러한 과도한 실행횟수를 줄여 성능 문제를 해결하기 위함
사용 사례
Debounce : 연이어 호출되는 함수들을 그룹화해 하나의 이벤트만 발생시킴
Throttle : 이벤트를 일정 주기마다 발생하도록 함