실행 컨텍스트
실행할 코드에 제공할 환경 정보들을 모아 놓은 객체임
클로저를 지원하는 대부분의 언어에서는 동일한 개념이 있긴 함
스택 : 선입 후출
큐 : 선입 선출
1. 동일한 환경에 있는 코드들을 실행
2. 필요한 환경 정보들을 모아서 컨텍스트를 구성함
3. 이걸 콜 스택에 쌓음
4. 가장 위에 쌓여있는 컨텍스트와 관련있는 코드들을 실행함
5. 이런식으로 전체 코드의 환경과 순서를 보장함
작동 순서 예시
var a = 1;
function outer(){
function inner(){
console.log("inner",a,b)
a = 3;
}
inner();
console.log(a)
}
outer();
var b = 3;
1. js코드를 실행하는 순간 전역 컨텍스트가 콜 스택에 담김 (최상단의 공간은 코드 내부에서 실행 명령 없어도 자동 실행함)
1-1. 이때 전역 컨텍스트 정보는 이거임
var a = 1;
=> 전역 변수 a가 선언, 초기화 됨
outer()
=> 전역에서 outer 함수 선언됨. 이건 전역 스코프에 있는 거임
전역 this
=> window객체 전역 this로 설정됨
2. 전역 컨텍스트와 관련된 코드들을 순차로 진행함
2-1. outer함수 호출됨. 이때 새로운 함수 실행 컨택스트가 생성됨
2-2. outer함수 내에서 inner함수가 호출됨. 또 다른 실행 컨텍스트가 만들어짐

스택 구조는
어떤 실행 컨텍스트가 콜 스택 맨 위에 쌓이는 순간
현재 실행할 코드에 관여하게 되어 있음
기존의 컨텍스트는 새로 쌓인 컨텍스트보다 아래에 위치하기 때문임
실행 컨텍스트 구조

1. variable환경에 정보를 먼저 담음
2. 이걸 그대로 복사해서 lexical 환경을 만듦
variable lexical 내부는
environmentRecord + Outer-Environment Reference 로 이루어짐
environmentRecord에는 현재 컨텍스트와 관련된 코드 식별자 정보가 있음
그러니까 코드가 실행되기 전이어도 자바스크립트 엔진은 이미 환경에 속한 코드의 변수명들을 알고 있는 거임
이걸
자바스크립트 엔진은 식별자를 최상단으로 끌어올려놓은 다음 실행한다... 고 해석할 수도 있고
실제 코드가 실행되기 전에 메모리에 할당한다... 라고도 해석함
저게 호이스팅임
여기서 호이스팅이라고 하면 유의해야 할 점....
여기서 유명한
let / const / var 차이
var로 선언된 변수는 무조건 스코프 최상단으로 호이스팅됨
선언과 동시에 undefined로 초기화 되기 때문에 undefined 에러 뱉음
console.log(a)
// undefined
var a = 8;
실제로는 이렇게 동작하는 거임
var a = 3 이라고 했을 때
var a; // 선언과 동시에 undefined로 초기화 (호이스팅된 상태)
console.log(a); // 출력: undefined
a = 3; // 실제 값 3을 할당
console.log(a); // 출력: 3
var 쓰지 말라고 하는 이유는 이거 때문임
스코프 최상단으로 끌어올려지기 때문에 스코프를 무시함
if (true) {
var a = 5;
console.log(a); // 출력: 5
}
console.log(a); // 출력: 5
let과 const로 선언된 변수는 자동으로 초기화 안 해줌
할당을 해야 초기화 - 할당을 거침
console.log(b)
// referenceError
// 선언 자체가 없어서 발생하는 레퍼런스 에러. 자바스크립트 엔진이 현재 스코프 체인에서 해당 변수를 못 찾을 때
let b = 0;
블록 스코프를 가지기 때문에
최상단으로 끌어올려지는 var 단점 극복 가능
if (true) {
let a = 5;
console.log(a); // 5
}
console.log(a); // ReferenceError
그럼 let const는 최상단으로 끌어올려지지 않는 걸까?
=> 아님. 최상단으로 끌어올려짐. 다만 할당하기 전에는 못 쓰게 만들어 놓은 것 뿐 (위에 reference 에러)
호이스팅 예시
function a(x){
console.log(x) <= //1;
var x; <= 이미 매개변수 x가 최상단 선언이 되어 무시됨
console.log(x) // 1;
var x = 2; <= 재할당
console.log(x); // 2;
}
a(1)
함수의 매개변수는 var로 선언한 변수와 동일한 스코프를 가짐
(매개변수도 최상단으로 호이스팅을 하지만 함수 스코프임
하지만 var 선언보다 우선적으로 동작함)
function a(){
console.log(b) // 함수b 찍힘
var b = "1234";
console.log(b); // '1234'
function b(){}
console.log(b) /// '1234'
}
a()
순서는 이렇게 된다고 생각하는게 나음
함수 선언이 우선순위가 높기 때문에 b가 먼저 정의됨
function a() {
function b() {} // 함수 b가 먼저 정의됨
var b; // var b는 호이스팅되지만 무시됨
console.log(b); // 함수
b = "1234"; // 할당
console.log(b); // '1234'
console.log(b);
}
함수 선언문 함수 표현식
function a(){} // 함수 선언문, 함수명 a가 변수명
var b = function(){} // 익명 함수 표현식, b 가 함수명임
var c = function d(){} // 기명함수 표현식, 변수명은 c, 함수명은 d
console.log(sum())
console.log(add())
function sum (){return 1}
var add = function(){return 2}
TypeError: add is not a function
1
함수 선언문은 함수 자체를 끌어올리고
변수는 선언부만 끌어올려서 쓰기 때문에.. 값이 뭔지 모름... 함수처럼 쓰니까 함수 아니라고 에러. 그냥 add 찍었으면 undefined 났음. var니까 초기화까지 했으니까
함수 선언문을 안 쓰는 이유는 명확함
스코프가 없다보니 나중에 변수명 겹치면 덮어쓰게 됨....
'Js' 카테고리의 다른 글
for문 안에 setTimeout 걸면 어떻게 동작할까 (0) | 2024.11.04 |
---|
댓글