HTML 파일에서 아래와 같은 javascript 파일을 참조할 때 Cannot read properties of null (reading 'addEventListener')
라는 에러가 발생했다.
//ch03-5.js
const timer = setTimeout(() => {
console.log("Heropy!");
}, 3000);
const h1El = document.querySelector('h1')
h1El.addEventListener('click', () => {
clearTimeout(timer)
})
에러의 원인은 "addEventListener" 속성을 읽을 수 없기 때문에 발생한다. 에러 체크를 하지 않고 실행을 하는 HTML의 인터프리터 언어적 특성으로 인해 HTML이 모두 로드 되기 전에 자바스크립트 영역에서 HTML을 참조하기 때문이다. 그렇기 때문에 HTML이 모두 로드된 후 자바스크립트에서 해당 개체에 접근하도록 코드를 수정하면 작동한다. 일반적으로 script를 아래와 같이 body 아래에 배치한다.
//index.html
<body>
<h1>Hello world!</h1>
<ul></ul>
<script src="./ch03-5.js"></script>
</body>
이 외의 방법으로는 javascript 파일 자체를 변경하는 방법이 있다. 기존에 에러가 났던 부분을 익명 함수로 감싸고 window.onload에 할당해주면 script를 body에 넣지 않아도 정상 작동이 된다.
window.onload = function () {
const h1El = document.querySelector("h1");
h1El.addEventListener("click", () => {
clearTimeout(timer);
});
};
위의 방식은 window.onload()를 오버라이딩(재정의)해주어 돔트리 완성 후 실행된다.
window.onload 란?
자바스크립트에서 페이지가 로드되면 자동으로 실행되는 전역 콜백 함수로 웹 브라우저의 모든 요소들이 로드된 이후 호출된다.
웹브라우저 자체를 담당하는 window라는 객체가 웹 문서를 불러올때 문서가 사용되는 시점에 실행되는 onload 라는 함수를 내가 다시 재정의 한다는 개념이다.
하지만 window.onload()는 한 페이지에서 한 번만 적용이 가능하다. 따라서 아래와 같이 addEventListener() 메서드를 통해 load 이벤트를 받는 식으로 구성하면 얼마든지 중복해서 사용이 가능하다.
<html>
<body>
<script>
window.addEventListener('load', function() {
let a = document.getElementById('name');
a.style.color = "blue"
})
</script>
<p id="name">hello</p>
</body>