JS

[JS] DOM이벤트로 익히는 호이스팅과 즉시실행함수

Junly_21 2023. 10. 3. 15:54

html,css,JS로 DOM에 접근하여 이벤트를 발생시키는 실습을 하다가 의문을 발견했고, 그 의문을 따라가다보니 이론으로 알고있던 호이스팅과 계속 헷갈리던 즉시실행함수를 익히는 경험을 하여 글을 작성한다.

 

bold라는 className을 가진 버튼을 클릭시 alert가 뜨게 하려고 한다.

원래 하려던 예제의 html은 다음과 같았다.

 <body>
    <div class="toolbar">
      <button class="bold">Bold</button>
      <button class="italic">Italic</button>
    </div>

    <div class="editor" contenteditable="true">dddd</div>
    <script src="index.js"></script>
  </body>

그리고 JS는 다음과 같았다.

(() => {
  document.querySelector(".bold").addEventListener("click", () => {
    alert("hello");
  });
})();

 

className이 bold인 Bold버튼을 클릭하면 alert창이 hello가 정상작동하도록 함수를 작성하였다. (css는 임의로 입혀놓았다)

 

1.즉시실행함수 

 

그런데 JS의 함수 형태가 좀 이상하다. 일반적으로 알고있는 함수의 형태는 다음과 같다.

()=>{}

위의 코드는 함수를 선언하는 때에 사용하는 방식이고

(()=>{})()

 

이 코드는 그 함수를 소괄호로 감싸고, 옆에 소괄호를 또 붙여서 함수를 선언과 동시에 실행시키도록 하는 즉시실행함수인것이다.

 

형태에 의문을 가질 필요는 없다. MDN에 즉시실행함수는 원래 이렇게 생긴거라고 하니까.

 

아하, 즉시실행함수는 이거구나.

 

그런데 이번엔 addEventListener에 있는 콜백에서 의문이 들었다.

(() => {
  document.querySelector(".bold").addEventListener("click", () => {
    alert("hello");
  });
})();

그럼 콜백을 선언한 다른 함수로 빼볼수도 있는건가? 라는 생각이 들어서 빼보았다.

 

(() => {
  document.querySelector(".bold").addEventListener("click", alertHello);
})();

(() => {
  document.querySelector(".bold").addEventListener("click", alertHello()); //alertHello뒤에 소괄호
})();

function alertHello() {
  alert("hello");
}

그런데 위의 두 click이벤트를 받는 콜백함수에 alertHello와 alertHello()는 무슨 차이가 있는거지? 라는 생각이 들었고 실행한 결과...

 

첫번째 allertHello 는 클릭 시 이벤트가 발생하고

두번째 allertHello()는 위의 즉시실행 함수에서 외운것처럼 뒤에 소괄호가 붙어있으니 즉시실행함수로 처리되어

클릭시에 선언된 alertHello를 실행하는게 아니라 렌더링시에 alert를 즉시 띄웠다.

 

오호,,, 즉시실행함수를 또 배웠다.

 

2.호이스팅

 

이렇게 작성했는데 또 또 의문점이 꼬리를 물었다.

 

'그러면 함수를 화살표로 작성해도 되는건가?'

 

바로 작성해보았다.

 

 

(() => {
  document.querySelector(".bold").addEventListener("click", alertHello); //똑같은 alertHello를 화살표로 작성
})();

const alertHello = () => {
  alert("hello");
};

 

alertHello가 function 에서 const arrowFunction으로 바뀐것 뿐이다.

당연히 실행이 될 줄 알았으나.... 

 

어? 실행이 안된다. 왜그런거지?

 

점점 의문이 깊어져 또 다시 찾아보니 이번에는 호이스팅 때문이었다.

 

 

호이스팅에서 얼핏 공부했던 기억이 있다. 함수선언문은 최상단으로 호이스팅이 된다. var는 호이스팅이 된다.

console.log(x);
console.log(y);
var x = 3;
const y =3
add();

function add() {
  console.log("add");
}

잠깐 호이스팅 공부예문 코드를 보자면 add()는 실행이 된다. 함수 선언문이 호이스팅이 가능하기 때문이다.

 

x는 var x, console.log(x) , x=3 순으로 되어 console.log에 undefined가 출력된다.

 

y는 에러를 발생시킨다. Cannot accees 'y' before initialization. 에러로 초기화가 되지 않아서 접근이 안된다고 한다.(값을 변화할 수 없으니 var과 다르게 반드시 초기값 할당이 먼저 되어야하나보다)

 

그러면 아래 코드를 다시 보자.

(() => {
  document.querySelector(".bold").addEventListener("click", alertHello);
})();

function alertHello() {
  alert("hello1");
}

이 코드는 실행이 잘 된다.

왜? 

alertHello 함수 선언문이 호이스팅 되어있기 때문이다.

 

반면 아래 코드는 실행이 안된다.

(() => {
  document.querySelector(".bold").addEventListener("click", alertHello);
})();

const  alertHello = () => {
  alert("hello1");
}

왜? const로 선언이 되어있기 때문이다. 함수의 선언부를 맨 위로 끌어올려야 제대로 alert창이 출력이 되는 것이다.

 

 

 

느낀점

즉시실행함수, 호이스팅, 콜백, 함수뒤에 ()를 붙이냐 안붙이냐 이런 개념이 맨날 책으로만 봐대니까 조금씩 체화가 안되고 의문이 생기던 때가 많았었다.

 

그런데 이번에 단순히 alert창을 띄우려는 예제를 공부하려다가 예문이 단순하니만큼 깊게 공부를 해보았고, 계속 헷갈리던 개념들이 체화가 어느정도 된 것같아서 매우 헛되지 않은 시간을 보냈다.

 

이 포스팅도 나중에 내가 기억이 안될 때 '아 이런 포스팅이 있었지' 하고 다시 복습하기 위해 작성하였다.