• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    미해결

스코프 질문

24.04.10 15:32 작성 조회수 97

0

안녕하세요. 스코프 부분을 좀 더 공부하다가 헷갈려서 질문드립니다.

 

강의에서 예시로 들어주신

  for(var i=0; i<winBalls.length;i++){
    console.log("for문 돌아가는 중",i);
    setTimeout(()=>{
      console.log(winBalls[i],i);
      drawBall(winBalls[i],$result)
    },(i+1)*1000);
  }

이 코드에서는 for문이 먼저 돌아가서 i의 값이 6이 된 이후 setTimeout이 각각 1초, 2초, 3초, 4초, 5초 후 실행되기 때문에 이미 for문이 돌아가고 i값이 6이되어 console.log(winBalls[i],i); 의 결과로 출력되는 값이 강의와 같이 전부 undefined와 6이 되는 것으로 이해했습니다.

 

제가 아직 뒷강의를 듣지 못했지만 이번 강의 내용을 듣고 스코프 부분을 더 찾아보면서 함수는 렉시컬스코프가 적용된다는 것을 알게되었습니다.

 

그래서 아래 코드를 테스트 해보았는데요.

var arr=[];
for(var i=0; i<5; i++){
  arr[i] = function(){
    console.log("function 내부", i);
    return i;
  }
}
for(var func of arr){
  console.log(func());
}

결과로

function 내부 5

5

가 다섯번 출력되었습니다.

 

저는 for문이 돌아가는 과정이

1) i=0일 때,

for 문 내부에서 전역변수인 i=0이고, arr[0]=function() {..}으로 함수의 표현식이 나오는데, 렉시컬 스코프에 의해 함수 내부에서는 현재 전역변수 i에 할당되어있는 값인 0을 참조.

2) i=1일 때,

for 문 내부에서 전역변수인 i=1이고, arr[1]=function() {..}으로 함수의 표현식이 나오는데, 렉시컬 스코프에 의해 함수 내부에서는 현재 전역변수 i에 할당되어있는 값인 1을 참조.

이후, 각각 i=2,3,4일 때도 마찬가지일거라고 생각했습니다.

 

그런데, 생각과 다르게 출력되어서 제가 렉시컬 스코프와 블록스코프를 잘못 이해하고 있는 것인지 궁금합니다.

 

감사합니다!

답변 2

·

답변을 작성해보세요.

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2024.04.10

안녕하세요, 인프런 AI 인턴입니다.

hxhxhx님의 스코프 관련 질문은 “let과 var의 스코프 차이와 클로저(Closure)“에 관한 내용인 것으로 보입니다. 자바스크립트의 var와 let 키워드는 스코프(scope) 관리에서 큰 차이를 보여줍니다. var를 사용할 경우 함수 레벨 스코프(function-scoped)를 가지며, let을 사용할 경우 블록 레벨 스코프(block-scoped)를 가지게 됩니다.

첫 번째 예시에서 var로 선언된 i는 for문 전체에서 하나의 변수로써 작동하여, setTimeout이 실행되는 시점에는 i의 값이 이미 최종 값인 6에 도달한 상태입니다. 이로 인해 모든 setTimeout 콜백 함수에서 참조하는 i는 같은 값인 6을 가리키게 되어 결과적으로 undefined와 6이 출력됩니다.

두 번째 예시에서도 비슷한 일이 발생합니다. 여기서 var로 선언된 i는 전역 범위에서 단 하나로 취급되므로, 모든 arr에 할당된 함수들은 모두 마지막으로 할당된 i의 값, 즉 5를 참조하게 됩니다. 이러한 현상은 클로저 때문에 발생하는데, 클로저는 함수와 함수가 선언된 렉시컬 환경의 조합으로, 이 경우 모든 함수가 같은 전역 변수 i를 참조하게 됩니다.

렉시컬 스코프에 대한 추가적인 이해를 돕기 위해, 이와 관련된 질문과 답변 링크를 제공해드리겠습니다:

hxhxhx님의 질문에 직접적으로 답변을 제공하지는 못했지만, 제시된 링크들이 스코프와 클로저에 대한 깊이 있는 이해를 얻는 데 도움이 될 것입니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

0

첫 번째 for문에서는 arr[0] arr[1]... 이렇게 대입되지만

요기서 i는 이미 5가 되어있습니다. 함수 내부의 i는 5를 가리키고있고요.

두 번째 for문에서 함수를 호출해도 i는 5입니다.

렉시컬 스코프의 의미는 변수 i를 참조한다는 것이지 i의 값을 그때 당시에 고정해서 참조한다는 게 아닙니다.

hxhxhx님의 프로필

hxhxhx

질문자

2024.04.10

아하 제가 렉시컬 스코프를 좀 잘못 이해하고 있었네요.

두번째 for문에서 func()로 호출하게 되면, 그 때 첫번째 for문에서 정의된 함수에서 참조하는 변수는 전역변수 i이고, i가 이미 5가 되어있기 때문에 5가 출력되는거군요.

 

답변 감사합니다! 명쾌하게 이해되었어요.