티스토리 뷰
브라우저 콘솔의 Sources 탭에서 원하는 라인의 라인넘버를 클릭한 뒤 새로고침하면
해당 라인에 브레이크 포인트가 걸려 해당 라인에서 프로그램이 멈춰있게 된다.
아래와 같은 예시 코드를 디버깅할 때
<script>
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);
// console.log(v2, l2, c2);
</script>
2번 라인(n0 ='n0')에 브레이크 포인트를 걸고 우측 노란 표시된 버튼(한 줄씩 실행하는 버튼)을 클릭하면
Scope의 Global에서 n0를 확인할 수 있다.
→ 변수 선언 시 var, let, const 등을 붙이지 않고 이름만 주면 그 값은 Global에 저장된다.
ESC를 눌러 console을 열고, n0를 입력하면 n0값을 가져온다.
→ 자바스크립트는 어떤 변수를 읽으려고 할 때 Scope에서 변수를 찾는다. Scope의 Script 안에 변수가 없으면 Global에서 찾는다.
3번 라인(var v0='v0')을 실행하면 마찬가지로 Global에서 v0를 찾을 수 있다.
→ var를 사용하여 변수 선언 시, 아무것도 사용하지 않고 변수 선언했을 때와 마찬가지로 Global에 저장된다.
4번 라인(let l0='l0')을 실행하면 Script의 l0 값이 'l0'가 된다.
이 l0를 콘솔에서 호출할 때 Script Scope에서 먼저 l0 값을 찾고 있으면 그 밑으로는 확인하지 않는다.
5번 라인(const c0='c0')도 마찬가지이다.
console.log로 변수들을 찍었을 때,
console.log(v0, n0, l0, c0) 의 경우, 4개의 변수 모두 찍히는걸 볼 수 있고
console.log(window.v0, window.n0, window.l0, window.c0) 의 경우, Global에 있는 변수만 찍히는 걸 볼 수 있다.
위 사진에서 Global Scope를 보면 window라고 표시되어있는걸 볼 수 있는데
웹브라우저에서 동작하는 자바스크립트는 window객체가 Global객체 또는 Global Scope이라고 할 수 있다.
어디에서 코드를 실행하던지 Scope상에서 global은 항상 존재한다.
→ 어디에서 실행하던 global은 접근가능하다.
→ 자바스크립트는 global을 window객체에 저장하는 것
다음은 fn1()함수로 다이브하여 살펴보면, (아래 노란 표시된 버튼을 누르면 함수 안으로 들어갈 수 있다.)
Call Stack에서 실행한 함수 이름을 확인할 수 있다.
→ Execute context가 Call Stack에 쌓인다.
Call Stack에서 anonymous를 클릭하면 함수를 실행하기 이전과 같아진다. (scope 등)
→ anonymous라는 스택은 예제 코드에서 함수말고 함수 바깥 쪽 코드들이 접근할 수 있는 변수의 scope을 보여준다.
→ 최초로 생기는 anonymous라는 execute context는 전역에서 접근할 수 있는 execute context로 global execute context라고 부른다.
fn1이라는 스택은 fn1 함수 내부의 코드들이 접근할 수 있는 변수의 scope을 보여준다.
→ fn1은 함수를 위해 만들어진 execute context로 function execute context라고 부른다.
fn1으로 들어와서 보면 local scope이 추가된 것을 확인할 수 있다.
함수의 첫번째 줄 n1='n1'을 실행해보면 global에 n1이 추가되었다.
→ 변수에 아무런 키워드를 붙이지 않고 변수의 이름을 사용하면 무조건 global scope으로 들어간다.
global scope은 프로그램에서 단 하나밖에 존재하지 않는 공간이고, 이미 수많은 함수와 변수가 존재한다.
global에 추가되도록 코딩할 경우(키워드 없이 변수 선언 등) 기존에 있는 변수가 바뀐다거나 하는 등의 문제가 발생할 수 있다.
함수의 두번째 줄(var v1='v1')을 실행하면 local scope에 v1값이 들어온다.
let l1, const c1을 실행하면 마찬가지로 local scope에 값이 들어오는 것을 확인할 수 있다.
fn1 함수 안에서 v0를 호출할 경우,
Local Scope에서 먼저 찾고 그 다음 Script Scope에서 찾고 그 다음 Global Scope에서 찾는다.
이렇게 Local Scope - Script Scope - Global Scope가 서로 연결되어 있는 것을 Scope Chain이라 한다.
fn1 함수 안에서 fn2 함수를 실행하면 scope와 call stack은 아래와 같이 바뀐다.
call stack은 실행한 순서대로 쌓였다.
fn1의 scope은 scope chain 안에 들어가 있지 않고 fn2의 local만 들어가 있다.
fn2 함수를 한 줄씩 실행시켜보면
n0, n1, n2는 global scope에 있기 때문에 12번 라인에서 console을 실행하면 세 값 모두 잘 찍힌다.
v0, v2도 local scope과 global scope에 존재하기 때문에 console에 잘 찍히고,
l0, l2, c0, c2도 local scope과 script scope에 존재하기 때문에 console에 잘 찍힌다.
하지만 v1, l1, c1의 경우 fn2의 scope chain 내에 없는 변수이기 때문에 호출할 경우 에러가 발생한다.
(v1, l1, c1는 fn1의 local scope 안에서 만들어지기 때문에 접근 불가)
fn2를 쭉 실행해서 바깥으로 나가면 Call Stack에서 fn2의 execute context가 제거된다.
fn1에서도 바깥으로 나가면 마찬가지로 fn1의 execute context가 제거된다.
→ global execute context만 남는다.
정리
global execute context에서 실행될 때 | function execute context에서 실행될 때 | |
Scope | ||
a = 1 | Global | Global |
var a = 1 | Global | Local |
let a = 1 | Script | Local |
const a = 1 | Script | Local |
참고 자료
🔗 [생활코딩] JavaScript - Execute context
🔗 [freeCodeCamp] JavaScript Execution Context – How JS Works Behind The Scenes
🔗 자바스크립트 - 스코프 체인(scope chain)란?
'개발공부 > 🟨 JavaScript' 카테고리의 다른 글
[JS] 자바스크립트 비동기 처리 (0) | 2023.01.29 |
---|---|
[JS] 호이스팅 (Hoisting) (0) | 2023.01.18 |
[JS] 클로저 (Closure) (0) | 2023.01.09 |
[JS] 이벤트 루프 (Event Loop) (0) | 2022.09.30 |
[JS] 내가 놓쳤던 자바스크립트 기초문법 정리 (0) | 2022.08.15 |
프론트엔드 개발자 삐롱히의 개발 & 공부 기록 블로그