클로저에 대한 질문입니다

조회수 541회

안녕하세요. Javascript 공부 중 모르는 것이 있어 질문 드립니다.

for(var i=0; i<36; i++) {
  document.getElementById("seat"+i).onclick = function(i) {
    return function(event) {
      showSeatStatus(i); 
    }
  }(i); // 이 부분!!
}

이 코드에서 다른 건 다 이해가 되는데 onclick 이벤트 처리 함수 끝에 (i)가 붙는 이유를 모르겠습니다. Closure란 것은 무엇인지 알지만 저 부분만 잘 모르겠더군요. 저 부분을 없애면 또 함수가 제대로 작동하지 않습니다. ㅜㅜㅜ

  • 아래는 제가 참고한 stackoverflow 링크입니다. stackoverflow

1 답변

  • 좋아요

    1

    싫어요
    채택 취소하기

    실제 클릭이 실행되는 시점은 for문이 다 돌아서 i값이 36이 된 후 입니다.

    제대로 동작하지 않는다고 하신 상황을 예측해 보자면, 모든 엘리먼트의 클릭 후 동작이 36번 인덱스만을 바라보고 동작할 겁니다.

    실제 36번 인덱스에 해당하는 데이터 혹은 엘리먼트는 없을 것이고 어딘가에서 참조 에러가 나겠죠.

    첨부해 주신 위 코드가 잘 이해가 안 되는 이유는 함정이 포함된 코드이기 때문입니다.

    실제로 이해를 돕기 위한 코드는 아래와 같이 되어야 합니다.

    for(var i=0; i<36; i++) {
      document.getElementById("seat"+i).onclick = function(index) { //  fixed
        return function(event) {
          showSeatStatus(index);  // fixed
        }
      }(i); // 이건 꼭 넣어주셔야 합니다.
    }
    

    이렇게 되면 클로저에 바인딩 된 변수가 뭐가 될까요? iindex라는 이름으로 바인딩 되어서 이 후에 클릭 이벤트가 발생해도 i 값을 유지할 수 있어서 문제가 되지 않습니다.

    참고로 자바스크립트의 scope, Function Expression, IIFE도 추가로 알아야 위 질문하신 코드의 형태에 대해서 헤깔리지 않을 겁니다.

    기억하세요. 비동기 코드 흐름 제어, 팩토리 패턴, 자바스크립트 안티 패턴 회피에 클로저는 유용합니다. 그 이유는 로컬 변수를 바인딩 할 수 있기 때문입니다.


    위와 비슷한 현상을 해결 할 수 있는 다른 방법은 Array.forEach 를 사용하는 것인데, 질문의 상황은 배열을 순회하는 것이 아니므로 해당되지 않겠네요.

    ES6를 사용한 더 단순한 방법은

    for(let i=0; i<36; i++) { // var -> let
      document.getElementById("seat"+i).onclick = function(event) {
          showSeatStatus(i);  // use "i"
      };
    }
    
    • 아 jigda님의 코드를 보니 아래의 괄호가 무엇인지 알겠어요!! function에 argument로 변수를 할당한단 뜻이군요!! 손성훈 2019.6.28 23:57
    • 제가 i를 계속 쓴 것은 어떻게 argument를 할당해야 하는지 몰라서 인데 덕분에 알게 되었습니다. 감사합니다 손성훈 2019.6.28 23:58

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)