본문 바로가기
  • soldonii's devlog
Javascript 공부/Advanced Javascript(-)

자바스크립트의 스코프 : 함수 스코프와 블록 스코프

by soldonii 2019. 8. 29.

*Udemy의"Advanced Javascript Concepts"강의에서 학습한 내용을 정리한 포스팅입니다.

*자바스크립트를 배우는 단계라 오류가 있을 수 있습니다. 틀린 내용은 댓글로 말씀해주시면 수정하겠습니다. 감사합니다. :)


함수 스코프 vs. 블록 스코프

용어가 헷갈리니 한 번 정리하고 넘어가자.

- 스코프(scope) : 함수가 실행될 때, 함수 내에서 변수에 대한 접근이 어떻게 되는지를 나타내는 용어이다.(함수의 실행 컨텍스트 내에서의 변수 환경이 무엇인지) 스코프는 함수를 기반으로 한 용어이다.

- 컨텍스트(context) : this 키워드의 값이 무엇인지를 나타내는 용어이다. 현재 실행 컨텍스트 내에서 어떤 객체를 참조하고 있는지를 의미한다. 컨텍스트는 객체를 기반으로 한 용어이다.

 

스코프 : 함수가 선언되면 무조건 스코프가 생성된다.
컨텍스트 : 함수가 속해있는 객체가 무엇인지를 의미한다.
  (만약 함수가 글로벌 스코프에서 선언되었다면, 이 때의 컨텍스트는 global(window)이다.)

# 함수 스코프

자바스크립트는 기본적으로 함수 스코프를 따르는 언어이다. 함수 스코프를 따른다는 의미는, 새로운 함수가 생성될 때마다 새로운 스코프가 발생된다는 뜻이다.(자바스크립트와 달리 대부분의 언어는 블록 스코프를 따른다.)

if (5 > 4) {
  var secret = '12345';
}

secret; // '12345'

 

자바스크립트가 함수 스코프라는 것은 위 코드를 통해서 알 수 있다. 위 코드에서 함수가 선언되어 있지 않기 때문에 새로운 환경, 새로운 스코프가 형성되지 않는다. 스코프가 형성되지 않으므로 동일한 실행 컨텍스트 내에 존재하는 것이다.(글로벌 실행 컨텍스트) 그렇기 때문에 어디에서나 secret 변수에 대한 접근이 가능하고, 따라서 '12345'를 출력하게 된다.

 

function a() {
  var secret = '12345'; 
}
secret; // ReferenceError

 

반면 여기에서는 함수를 만들고, 그 안에 변수를 저장했다. 이 경우 함수 생성과 동시에 a 함수에 대한 새로운 실행 컨텍스트가 생성이 되고, 이 실행 컨텍스트 내부에 존재하는 변수 환경(variable environment)에 secret 변수가 저장된다. 

따라서 함수 외부에서 secret에 접근하려고 할 경우 스코프가 다르기 때문에 해당 변수에 접근이 불가능하다.(함수 외부는 global scope이고, 함수 내부는 a 함수의 scope인데, 부모 스코프는 자식 스코프에게 간섭할 수가 없기 때문에 접근이 불가능한 것이다.)

 

# 블록 스코프

함수 스코프가 함수 생성시마다 새로운 스코프가 생성되는 것을 의미한다면, 블록 스코프는 말 그대로 블록 {}이 생성될 때마다 새로운 스코프가 형성되는 것을 의미한다. 원래 자바스크립트는 함수 스코프를 따르지만, let과 const 키워드의 등장으로 블록 스코프를 형성하는 것도 가능해졌다.

function loop() {
  for (var i = 0; i < 5; i++) {
    console.log(i);
  }
  console.log('final', i);
}
loop();
/*
0
1
2
3
4
final 5
*/

 

이 코드를 보면, for 문 안에서 변수 i를 var 키워드로 초기화 해줬다. 이 경우에는 블록 스코프가 아닌 함수 스코프를 따르게 되는데, for 문 안쪽과 바깥 쪽에서 모두 변수 i에 접근해서 console.log를 하고 있다. 이 때는 어차피 loop이라는 함수 스코프 안에 둘 모두 존재하기 때문에 문제 없이 for문 안이든 밖이든 문제 없이 i에 접근해서 값을 출력한다.

 

function loop() {
  for (let i = 0; i < 5; i++) {
    console.log(i);
  }
  console.log('final', i);
}
loop();
/*
ReferenceError: i is not defined
*/

 

반면 for문 내에서 변수 i를 let으로 선언할 경우에는 달라진다. let으로 선언하는 순간, 변수 i는 for문 내에만 종속되며, for문 외부에서는 i에 접근할 수가 없다. 스코프가 다르기 때문이다. 

댓글