오늘은 javascript의 기본다지기 첫날로 js의 기본이자 반드시 알고 있어야 할 핵심 개념들에 대해 정리를 진행해보고자 한다.
아래의 질문들에 대해 답을 구해보며, 실행컨텍스트의 개념에 대하여 공부하고 정리를 시작해보겠다.
스코프란? js는 함수레벨 스코프인가 블록레벨 스코프를 따르는가?
실행컨텍스트의 정의는 무엇인가?
js의 실행 컨텍스트가 포함하고 있는 정보(속성)는 무엇이 있는가?
다음 코드에서의 출력되는 a의 순서와 값을 올바르게 대답할 수 있는가?
var a = 1;
function outer(){
console.log(a); // 1번
function inner(){
console.log(a); //2번
var a = 3;
}
inner();
console.log(a); //3번
}
outer();
console.log(a); //4번
(a는 1번 2번 3번 4번 차례대로 실행되고, 각 1, undefined, 1, 1 이 출력됩니다.)
0. 스코프란?
스코프는 변수의 유효범위로, 해당 변수에 접근할 수 있는 범위를 말한다.
스코프를 이해하기 위해서는 전역변수와 지역변수의 개념을 알아야한다.
전역변수(global)는 js의 가장 바깥 범위에 선언된 변수로 window 객체에 변수를 만드는 것을 말한다.
지역변수(local)은 지역(함수)내에서 선언된 변수이며, 해당 지역(함수)와 그 지역의 내부 지역(내부함수)에서 참조할 수 있다.
함수스코프와 블록스코프 규칙 중 js는 함수스코프를 따르며, 함수스코프는 함수 내부에서 선언한 변수는 지역변수, 함수 외부에서 선언한 모든 변수를 전역변수로 취급한다.
let x = 'global';
function exFunc() {
let x = 'local'
x = 'change';
}
exFunc();
console.log(x); // 'global'
여기서 전역변수는 함수가 아닌 외부에서 선언된 x = 'global'이며, 지역변수는 exFunc() 내부에서 x = 'local' 이다.
exFunc() 가 실행되며 exFunc() 함수 내부의 지역변수 x 는 'local' 에서 'change'로 변하지만, 전역변수는 그대로 'global'이며, 이에 따라 'global'이 출력된다.
즉 지역변수가 전역변수의 영향을 미칠 수 없는 상황이다. 하지만 지역변수가 전역변수를 바꿀 수 있는 방법이 있는데, 이를 가능하게 하는 것이 스코프체인(scope chain)이다.
스코프체인(scope chain)의 핵심은 내부함수에서는 외부함수의 변수에 접근가능하지만, 외부함수에서는 내부함수의 변수에 접근할 수 없는 것이다.
스코프체인은 실행컨텍스트에 의해서 함수가 실행되는 순간에 생성(결정)되는데, 다음에서 실행컨텍스트에 대해 알아보겠다!
1. 실행컨텍스트란?
(a) 정의

실행컨텍스트는 함수를 실행할 때 필요한 환경정보 이다.
구체적으로 js에서 실행컨텍스트는 함수를 실행할 때 필요한 환경정보를 담은 객체가 생성되므로 이를 가르킨다.
JS에서 동일한 조건/환경을 지니는 공간은 함수와 전역공간을 의미하기 때문에 함수의 개수 + 1 만큼의 실행컨텍스트가 생성됩니다.
(b)실행컨텍스트의 4가지 원칙
실행컨텍스트에는 아래와 같은 대표적인 원칙 4가지가 존재한다.
- 전역 컨텍스트가 최초 생성 후, 함수 호출 시 마다 하나의 컨텍스트가 생성된다.
- 컨텍스트가 생성 될 때, 컨텍스트 객체에 변수객체, 스코프체인, this 가 생성된다.
- 컨텍스트 생성 이후 함수가 실행될 때 사용되는 변수들은 변수 객체 안에서 먼저 찾고, 없다면 스코프체인을 따라 올라가며 찾는다.
- 함수 실행이 마무리 되면, 해당 컨텍스트는 사라진다.(클로저 제외)
이제 이 4가지 원칙에 따라 위의 예제를 차례대로 실행해보겠습니다.
(c) 실행컨텍스트 예제로 살펴보기
var a = 1; // (1) 전역변수a 선언 (3) 전역변수 1 대입
function outer(){ // (2) outer함수선언 && 함수대입 by 호이스팅
console.log(a); // (6) outer context a탐색 -> global context a탐색 -> 1출력
function inner(){ // (5) inner함수선언 && 함수대입 by 호이스팅 (8)지역변수 a 선언
console.log(a); // (9) inner context에서 a 탐색 -> 선언만 되었음 -> undefined출력
var a = 3; //(10) 지역변수 a에 3할당 (11)inner context 종료
}
inner(); // (7) inner함수호출 -> inner함수 실행컨텍스트 활성화
console.log(a); //(12) outer context a탐색 -> global context a탐색 -> 1출력
} //(13)outer함수 실행컨텍스트 종료
outer(); // (4) 함수outer호출 -> outer 함수실행컨텍스트 활성화
console.log(a); //(14) global cotext a 탐색 -> 1출력
1단계. 전역 컨텍스트: (0) ~ (4) && (14)~(15)
(0): 전역컨텍스트(global)가 활성화됩니다.
(1): 컨텍스트는 활성화와 함께 변수객체에 사용가능한 변수를 담습니다.
따라서 전역변수 a가 선언됩니다.
(2) : 함수의 선언 시 선언과 대입을 동시에 진행하는 호이스팅에 의해 바로 해당 함수가 할당됩니다.
(3): (1)에서 선언된 전역변수 a에 1의 값이 할당 됩니다.
(4): outer() 함수가 호출되며, outer 함수 실행 컨텍스트를 활성화 시킵니다.
최종적으로 1단게에서 전역컨텍스트는 변수객체 : { [a: 1, outer: Function] } , 스코프체인:{ ['전역변수객체']} , this:window 를 가지게 됩니다.
2단계. Outer함수 컨텍스트: (5) ~ (13)
(5): 호이스팅에 의해 inner함수가 선언,할당 됩니다.
(6): 현재 컨텍스트의 변수객체에서 a를 탐색합니다.
outer 컨텍스트 에서는 a가 존재하지 않으므로 스코프체인을 따라 전역(global)컨텍스트에서 a를 탐색합니다.
전역 컨텍스트의 a의 값인 1을 출력합니다
(7) inner 함수를 호출합니다.
함수의 호출과 동시에 inner 컨텍스트가 실행됩니다.
3단계. Inner함수 컨텍스트
(8): 지역변수 a가 선언됩니다.
(9): 현재 컨텍스트인 inner 컨텍스트에서 a를 탐색합니다. inner 컨텍스트에는 선언된 a만이 존재하므로 undefined를 출력하게 됩니다.
(10): 지역변수 a에 3의 값이 할당 됩니다.
(11): inner 컨텍스트가 종료됩니다.
(12): 현재 컨텍스트인 outer 컨텍스트에서 a 탐색 -> 전역컨텍스트에서 a 탐색 -> 1출력
(13): ouuter 컨텍스트가 종료됩니다.
다시 전역컨텍스트
(14): 현재컨텍스트인 전역컨텍스트에서 a를 찾아 1을 출력합니다.
(15): 전역컨텍스트가 종료되며 끝.

(4) 마무리
위의 사례를 통해 실행컨텍스트에 대하여 알아보았다.
요약해보면 스코프란 '변수에 접근할 수 있는 범위' 를 뜻하며,
스코프체인은 실행컨텍스트에 의해 함수가 호출되었을 때 결정되는 스코프를 의미하며, 내부함수에서 외부함수의 변수는 접근가능하지만, 외부함수에서 내부함수의 변수는 접근할 수 없음을 뜻한다.
실행컨텍스트는 함수가 실행될 때 필요한 환경정보를 담은 객체이며, 총 3가지 속성(변수객체와 스코프체인, this)을 가지고 있다.
컨텍스트 생성 시 해당 컨텍스트에 존재하는 변수들이 가장 먼저 선언되게 되는데, 이 개념을 호이스팅이라고 한다. 이때 함수는 변수의 선언과 동시에 함수자체의 할당이 이루어지는 특징을 갖는다.
사실 굉장히 간단한 예제이지만, 지역변수와 전역변수, 스코프체인, 호이스팅 , 실행컨텍스트 등의 개념을 명확히 이해하도록 도와주는 예시가 되었다.
다음으로는 클로저에 대한 포스팅으로 돌아오겠습니다.
'Web > Javascript' 카테고리의 다른 글
스택(Stack)과 큐(Queue)의 개념 정리_(2) Queue (0) | 2021.01.19 |
---|---|
스택(Stack)과 큐(Queue)의 개념 정리_(1) Stack (0) | 2021.01.19 |
[객체지향프로그래밍(OOP)] (1) 객체지향프로그래밍이란? (0) | 2021.01.15 |
[JS/Str] 문자열(str)자르기 총 정리: substr( ), substring( ), slice( ) (0) | 2020.12.27 |
댓글