프론트엔드 로드맵의 자바스크립트 과정에 있는 Netflix 랜딩 페이지 클론구축 영상을 보며 부족한 부분을 정리한 내용입니다.
▶codepen.io
강의를 보며 구현했던 자바스크크립트 코드를 다시 한번 작성하며 공부하던 중 아래와 같은 에러가 발생했습니다.
Uncaught TypeError: Cannot read properties of undefined (reading 'add') at HTMLDivElement.selectItem
html
<div class="container">
<div id="tab-1" class="tab-item tab-border">...</div>
<div id="tab-2" class="tab-item">...</div>
<div id="tab-3" class="tab-item">...</div>
</div>
javascript
const $tabItem = document.querySelectorAll('.tab-item')
const $tabContent = document.querySelector('.tab-content-item')
//에러발생 부분
const selectItem = () => {
this.classList.add('tab-border');
}
$tabItem.forEach(item => item.addEventListener('click', selectItem ))
에러 발생의 원인은 일반함수가 아닌 화살표함수로 작성을 하며 this 범위가 달라졌기 때문입니다. 자바스크립트 내부에서의 함수는 전역객체를 가르키지만 화살표함수에서의 this는 상위 스코프의 this를 가르킵니다.
따라서 위 코드는 아래와 같이 수정을 해야합니다.
const $tabItem = document.querySelectorAll('.tab-item')
const $tabContent = document.querySelector('.tab-content-item')
function selectItem() {
removeBorder();
this.classList.add('tab-border');
}
function removeBorder() {
$tabItem.forEach(item => item.classList.remove('tab-border'))
}
$tabItem.forEach(item => item.addEventListener('click', selectItem ))
만약 화살표함수를 쓴다면 다음과 같이 작성이 가능할 것 같다.
const removeBorder = () => {
$tabItem.forEach(item => item.classList.remove('tab-border'))
}
const selectItem = (e) => {
removeBorder()
const item =e.target.closest('.tab-item')
item.classList.add('tab-border')
}
$tabItem.forEach(item => item.addEventListener('click', selectItem ))