📌 참고 영상
JavaScript - Execute context - YouTube
💻 분석해 볼 코드
n0='n0';
var v0='v0';
let l0='l0';
const c0 = 'c0';
console.log(v0, n0, l0, c0);
console.log(window.v0, window.n0, window.l0, window.c0);
function fn2(){
n2='n2';
console.log(n0, n1, n2);
var v2='v2';
console.log(v0, v2);
// console.log(v1)
let l2='l2';
console.log(l0, l2);
// console.log(l1);
const c2='c2;';
console.log(c0, c2);
// console.log(c1);
}
function fn1(){
n1='n1';
var v1='v1';
let l1='l1';
const c1='c1';
fn2();
}
fn1();
console.log(n2);
브라우저 콘솔 창을 열고 Sources로 들어가 n0 = 'n0' 코드가 있는 줄에 breakpoint를 설정한 후 새로고침을 하면 디버깅이 시작된다.
1.
n0 = 'n0'이 어디 저장되었는지 Scope에서 살펴보면 Global이라는 곳 어딘가에 저장되어 있는 것을 볼 수 있다. 이처럼 예약어 없이 그냥 변수를 선언한 경우 Global Scope에 저장된다.
따라서 console 창에 그냥 n0을 입력하면 'n0'이 정상적으로 출력되는 것을 볼 수 있다.
2.
var v0 = 'v0'의 경우도 Global이라는 곳에 저장되어 있는 것을 볼 수 있다.
var로 변수를 선언한 경우에도 Global Scope에 저장되는 것을 알 수 있다.
3.
let l0 = 'l0'의 경우에는 Scope에서 어디에 저장되었는지 살펴보면 Script에 저장되어 있는 것을 볼 수 있다.
즉, let으로 변수를 선언하면 Script Scope에 저장되게 된다.
콘솔에 l0을 입력하면 'l0'이 잘 출력되는 것을 볼 수 있는데, JS는 Script Scope에서 먼저 해당 변수가 있는지를 찾아본다. 이 경우에는 Script에 변수가 존재하므로 그것을 가져오고, Global까지 살펴보지 않게 된다.
4.
const c0 = 'c0'의 경우에도 Script Scope에 저장되게 된다.
즉, const로 변수를 선언하면 let 때와 마찬가지로 Script Scope에 저장되게 된다.
5.
console.log(v0, n0, l0, c0)을 하면 정상적으로 v0 n0 l0 c0이 콘솔에 출력되는 것을 볼 수 있다.
JS에서 window 객체는 global scope라고 할 수 있다.
6.
v0, n0는 이전에 Global에 저장되어 있었고, 따라서 window.v0, window.n0 이런 형태를 통해 접근이 가능하다. (어디서 실행하던지 Scope 상에서 항상 Global이 바닥에 깔려 있기 때문에 Global에는 항상 접근이 가능하다.)
but let과 const로 선언된 l0과 c0은 Global이 아닌 Script에 저장이 되어 있기 때문에 Global에 있는 window 객체를 통해 접근하는 것이 불가능하다. window 객체에는 l0과 c0에 대한 정보가 들어 있지 않다.
따라서 console.log(window.v0, window.n0, window.l0, window.c0) 의 결과는 v0 n0 undefined undefined 이 된다.
7.
f1() 함수가 실행되면 Call Stack이라는 곳에 우리가 실행한 함수의 이름이 적히는 것을 볼 수 있다.
실행 컨텍스트(excute context)는 Call Stack이라는 곳에 쌓인다.
Call Stack은 폴더로, Scope은 Call Stack 안에서 접근할 수 있는 파일들을 보여주는 것이라고 비유할 수 있다.
8.
f1() 함수 안으로 본격적으로 들어가면 Local이라는 Scope이 생성되고, 그 안에 예약어(var, let, const)로 선언된 변수들이 해당되어 있는 것을 볼 수 있다. (아직 값은 undefined)
앞에 아무 키워드도 붙이지 않고 선언한 n1의 경우 어느 부분에서 선언하든 global scope으로 들어가는 것을 알 수 있다.
9.
f1() 실행 중 전역 변수 v0을 불러오는 것이 가능하다.
10.
f2 함수를 실행하면 Call Stack에 f2 함수에 대한 실행 컨텍스트가 새로 쌓이게 된다.
그리고 Local에는 함수 f2 안에 존재하는 변수들인 c2, l2, v2로 채워지게 된다. (예약어를 붙이지 않은 n2의 경우 global scope에 해당됨)
f2 함수를 실행하면 Local Scope가 f2의 것으로 바뀌기 때문에 f1 함수의 Local Scope와는 연관이 없다.
따라서 console.log(v0, v2)는 정상적으로 실행 (v0은 global scope에서, v2는 현재 local scope에서 찾음)되는데 console.log(v1)의 경우 현재 실행 컨텍스트의 scope에서 찾아볼 수 없기 때문에 에러가 난다.
✏️ 정리
➡️ global execute context에서 실행될 때
변수 선언 | Scope |
a = 1 | Global Scope |
var a = 1 | Global Scope |
let a = 1 | Script Scope |
const a = 1 | Script Scope |
➡️ function execute context에서 실행될 때
변수 선언 | Scope |
a = 1 | Global Scope |
var a = 1 | Local Scope |
let a = 1 | Local Scope |
const a = 1 | Local Scope |
'Javascript study' 카테고리의 다른 글
[JS] IndexedDB (2) | 2023.08.27 |
---|---|
[JS] Closure (0) | 2023.08.27 |
[JS] 실행 컨텍스트 (1) (0) | 2023.08.25 |
[JS] 렉시컬 환경, this 정리 (2) | 2023.08.23 |
[JS] FileReader (0) | 2023.08.21 |
댓글