이미지 출처 링크
스코프(scope)는 현제 실행되는 컨텍스트(context)를 말한다. 여기서 컨텍스트는 값과 표현식이 "표현"되거나 참조 될 수 있음을 의미한다. 만약 변수 또는 다른 표현식이 "해당 스코프"내에 있지 않다면 사용할 수 없다. 스코프는 또한 계층적인 구조를 가지기 때문에 하위 스코프는 상위 스코프에 접근할 수 있지만 반대는 불가하다.
context
의 사전적 의미
(명사)
- (어떤 일의) 맥락, 전후 사정
- (글의) 맥락, 문맥
함수는 자바스크립트에서 클로저 역할을 하기 때문에 스코프를 생성하므로 함수 내에 정의된 변수는 외부 함수나 다른 함수 내에서는 접근 할 수 없다. 예를 들어 다음과 같은 상황은 유효하지 않다.
let b = 1;
function hi() {
const a = 1;
let b = 100;
b++;
console.log(a, b);
}
// console.log(a);
console.log(b);
hi();
console.log(b);
이 상태에서 실행시키면 콘솔에는 다음과 같이 찍힐 것이다.
1
1, 101
1
1번째 줄의 1
은 예제 코드의 1행에서 선언된 b의 값이 찍힌것이고
2번째 줄의 1, 101
은 예제 코드의 4행에서 선언된 a 와 5행에서 선언된 b 에서 b++ 된 값이 찍힌것이며
마지막 3번째 줄 1
은 다시 예제코드 1행의 b값이 찍힌것디다.
만약 예제코드 10행 부분의 주석을 푼다면
console.log(a); //ReferenceError
a
는 hi()
함수 안에서 선언된 지역변수 이므로 전역변수처럼 호출하면 ReferenceError
가 나게된다.
a
변수를 찍어보고 싶다면
console.log(a)
를 hi()
함수 블럭 안으로 옮기거나, 10번째 줄 이전에 a
전역 변수 선언을 해주어야 한다.
JavaScript에서 호이스팅(hoisting) 이란, 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미한다. var
로 선언한 변수의 경우 호이스팅 시 undefined
로 변수를 초기화한다. 반면 let
과 const
로 선언한 변수의 경우 호이스팅 시 변수를 초기화하지 않는다.
JavaScript는 함수의 코드를 실행하기 전에 함수 선언에 대한 메모리부터 할당한다. 덕분에 함수를 호출하는 코드를 함수 선언보다 앞서 배치할 수 있다. 예를 들어,
function catName(name) {
console.log("제 고양이의 이름은 " + name + "입니다");
}
catName("호랑이");
/*
결과: "제 고양이의 이름은 호랑이입니다"
*/
위의 코드 조각이 일반적으로 코드를 작성하는 순서라면,
함수를 선언하기 전에 먼저 호출했을 때의 예제도 보자.
catName("클로이");
function catName(name) {
console.log("제 고양이의 이름은 " + name + "입니다");
}
/*
결과: "제 고양이의 이름은 클로이입니다"
*/
함수 호출이 함수 자체보다 앞서 존재하지만, 이 코드는 동작한다. 이것이 JavaScript에서 실행 맥락이 동작하는 방식이다.
호이스팅은 다른 자료형과 변수에도 잘 작동한다. 변수를 선언하기 전에 먼저 초기화하고 사용할 수 있는 것.
JavaScript는 초기화를 제외한 선언만 호이스팅한다. 변수를 먼저 사용하고 그 후에 선언 및 초기화가 나타나면, 사용하는 시점의 변수는 기본 초기화 상태(var
선언 시 undefined
, 그 외에는 초기화하지 않음)다. 예를 들어,
console.log(num); // 호이스팅한 var 선언으로 인해 undefined 출력
var num; // 선언
num = 6; // 초기화
반면, 다음 예제는 선언 없이 초기화만 존재한다. 따라서 호이스팅도 없고, 변수를 읽으려는 시도에서는 ReferenceError 예외가 발생합니다.
console.log(num); // ReferenceError
num = 6; // 초기화
let과 const로 선언한 변수도 호이스팅 대상이지만, var와 달리 호이스팅 시 undefined로 변수를 초기화하지는 않는다. 따라서 변수의 초기화를 수행하기 전에 읽는 코드가 먼저 나타나면 예외가 발생한다.
const num = 1
num; // 1
위 코드는 정상적으로 동작한다
num; // throws `ReferenceError`
const num = 1
num; // 1
const num = 1
구문 위의 num 은 TDZ에 있다.
ReferenceError: Cannot access 'white' before initialization
자바스크립트 에러가 발생한다.
그림 출처: https://dmitripavlutin.com/javascript-variables-and-temporal-dead-zone/
let
도 const와 같이 선언 줄 까지 TDZ의 영향을 받는다.
// Does not work!
count; // throws `ReferenceError`
let count;
count = 10;
따라서 let
변수도 선언 이후에 사용해야 한다.
레퍼런스:
https://developer.mozilla.org/ko/docs/Glossary/Scope
https://developer.mozilla.org/ko/docs/Glossary/Hoisting
https://ui.toast.com/weekly-pick/ko_20191014?fbclid=IwAR3fiR4wiv8kszL6Fz2KqwHpv-bTL8tNHElRN0q0ky5kpOP5BMqMS0wc-9k