자바스크립트 이런 이슈 혹시 아십니까?
조회수 1180회
<script language="JavaScript">
myTickets = new Array();
startPosArr = new Array();
endPosArr = new Array();
selItem;
eee2 = 0;
function setMyTicketList(){
alert("^^ : " + eee2);
}
위와 같은 코드에서 eee2를 alert하는 곳에서 다음과 같은 에러가 발생합니다.
Uncaught ReferenceError: eee2 is not defined
그런데 웃기는 것은 eee2의 전역변수 선언 위치를 맨 첫줄에 아래와 같이 선언하면 정상적으로 실행됩니다.
eee2 = 0;
myTickets = new Array();
startPosArr = new Array();
endPosArr = new Array();
selItem;
다른 언어에서는 있을 수 없는 현상이라서 좀 황당해서 질문드립니다. 감사합니다.
-
(•́ ✖ •̀)
알 수 없는 사용자
1 답변
-
우선 아래 답변은 제가 공부하려고 적는 것이라서 약간 틀린 곳들이 있을 수 있음을 알려드리며... 제가 이해한 것을 설명드리자면, 실행이 안 되는 것은
eee2
가 맨 뒤에 있어서가 아니라selItem
보다 뒤에 있기 때문에, 또는var selItem;
이라고 명시적으로 변수 선언을 안 했기 때문에 그런 겁니다. 참조오류(ReferenceError)의 문제입니다.ReferenceError 객체는 존재하지 않는 변수를 참조했을 때 발생하는 에러를 나타냅니다. (...) ReferenceError는 선언된 적이 없는 변수를 참조하려고 할 때 발생합니다. 출처: MDN
JS에서 존재한다는 것은 뭐냐? 선언(declare)되었다는 것입니다. 물론 다른 언어와 비슷하게 일단 선언만 하고 형과 값을 나중에 할당(assign)하는 것이 가능하죠. 그냥
setItem;
이라고만 적으신 것은 아마 그렇게 선언만 해두고 싶으셨던 것 같습니다.그런데 JS에서 참조한다는 것은 뭐냐? 해당 수준의 범위(scope)까지 그 존재를 땡겨올린(hoist) 다음 그걸 쳐다보고 지명한다는 것입니다. 호이스팅이라고 하는데, JS의 기본 동작은 함수를 먼저 호이스팅하고 그 다음에 변수들을 호이스팅하며, "뭔가 처음 보는 놈이 벌써 뭔가를 할당까지 받았다" 싶으면 변수로 선언된 것으로 보고 올라갈 수 있는 범위까지 땡겨올립니다.
따라서 다음 코드는 동작하죠.
x = 5; alert(x); // 예상하시는 바로 그 동작을 합니다.
하지만 다음 코드는 브라우저 개발자콘솔의 에러 외에 아무 일도 안 일어납니다.
x; alert(x);
왜냐? 할당도 안 받았고
var x;
하는 식으로 변수라는 선언도 못받은 놈을 뭣하러 전역범위까지 끌어올려다 주냐 이겁니다. 그래서 JS는 "야 잠깐만 이x
뭐야?"라는 의미의 참조오류를 던지고 처리를 중단합니다.
자 이제 올려주신 코드를 볼까요. 아래 코드는 로딩되자마자 개발자 콘솔에 selItem is not defined라는 참조오류를 찍고, 함수를 실행시키면 추가로 eee2 is not defined라는 참조오류를 또 찍습니다.
selItem; eee2 = 0; function setMyTicketList() { alert("eee2: " + eee2); }
그럴 만도 하죠.
setMyTicketList()
함수 호이스팅 됐고, 이제 변수들을 호이스팅하려고 보니까 갑자기selItem
이란 듣보잡이 보여서 전체 호이스팅이 중단된 겁니다. 그래서 뒤에서 대기 타고 있던 애먼eee2
까지 호이스팅을 못 받고undefined
신세가 됐거든요. 그러니 나중에setMyTicketList()
함수를 콜해본들eee2
가 뭔지 모르겠다는 에러만 만나게 됩니다.반면 아래 코드는
selItem
레퍼런스 에러까지는 내지만 함수 실행 자체는 시켜줍니다.eee2 = 0; selItem; function setMyTicketList() { alert("eee2: " + eee2); }
왜 되는지 이해되시겠죠? 매우 우연하게, 다행히,
eee2
는 존재되어 참조된 겁니다.보너스: 다음도 동작합니다. 아래 코드에서 총 3개의 객체는 모두 정상적으로 호이스팅 되었기 때문이죠. (아래 코드의
eee2
처럼 어떤 변수를var
,let
같은거 없이 그냥 바로 할당만 하는 방식의 호이스팅은 안 좋긴 한데 그건 좀 다른 얘기니까 생략...)var selItem; eee2 = 0; function setMyTicketList() { alert("eee2: " + eee2); }
예전에 취직면접 보고 다닐 때 호이스팅 아냐고 물어보는 걸 답 못 해서 개쪽당하고 나온 기억이 나서 공연히 자세히 적어봤습니다. 자세한 건 데모와 함께 좀더 탐구해 보기로 하시죠. 도움이 되었을까요?
댓글 입력