일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- jwt
- 항해99 사전스터디
- 리액트 메모
- 리액트 렌더링 최적화
- js배열 알고리즘
- 리액트 메모이제이션
- 항해99 미니프로젝트
- 실행컨텍스트
- 웹 크롤링
- 리덕스
- 알고리즘
- 렌더링 최적화
- 테스트 코드 툴 비교
- toggle-btn
- 함수형 프로그래밍 특징
- v8 원리
- 항해99
- 자바스크립트 엔진 v8
- 타입스크립트
- 코어자바스크립트
- chromatic error
- 리액트
- next js
- 웹팩 기본개념
- FP 특징
- Js module
- JS module system
- this
- gql restapi 차이
- 항해99 부트캠프
- Today
- Total
Jaeilit
코어 실행컨텍스트 본문
실행컨텍스트
실행할 코드에 제공할 환경 정보들을 모아놓은 객체
자바스크립트는 어떤 실행 컨텍스트가 활성화되는 시점에 선언 된 변수를 위로 끌어올리고(호이스팅) 외부 환경 정보를 구성하고, this 값을 설정 하는 등의 동작을 수행함.
# 스택과 큐
스택과 큐는 자료구조와 알고리즘에서도 나오는 개념임
스택 선입후출 (FILO)
스택은 쌓다라는 의미로 블럭을 밑에서 위로 쌓듯이 책을 쌓듯이 쌓는 구조를 의미함
쌓여있으니 당연히 맨 처음에 들어온게 맨 마지막에 나가게 된다.
호출스택이 쌓이는 스택구조에 너무 많은 스택이 들어가면 stack over flow 에러가 발생함.
예를 들어 100개만 저장할 수 있는 스택에 101개가 들어가면 stack over flow 에러가 발생.
큐 선입선출 (FIFO)
터널과 비슷하다 입구만 있고 출구가 없는 스택과 다르게 큐는 출구가 있어서
가장 먼저 들어온 게 가장 먼저 나갈수있다.
실행컨텍스트라는 주제로 이야기를 시작해놓고 갑자기 왜 스택과 큐를 살펴봤나?
<스택의 구조>
실행할 코드에 제공할 환경 정보들을 모아놓은 객체인 실행켄텍스트는 콜 스택으로 동작함.
동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고 콜 스택에 쌓음.
가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장함.
동일한 환경에서 실행 컨텍스트를 구성하는 방법
1. 전역공간
2. eval() 함수,
3. 함수
전역공간과 악마?로 취급받는 eval() 를 제외하면 우리가 흔히 실행하는 컨텍스트를 구성하는 방법은 함수를 실행하는 것 뿐
1. 호이스팅
선언부가 맨 위로 끌어올려진 것 처럼 보이는 것
선언부
var a
function outer()
--
교재내용 순서
1. 코드를 실행하는 순간 (1) 전역 컨텍스트가 콜 스택에 담김
2. (3) 에서 outer() 함수를 호출하면 자바스크립트 엔진은 outer에 대한 환경정보를 수집해서 outer 실행 컨텍스트를 생성한 후 콜 스택에 담음
3. 콜 스택의 맨 위에 outer 실행 컨텍스트가 놓인 상태가 됐으므로 전역 컨텍스트와 관련된 코드의 실행을 일시중단하고 대신 outer 실행 컨텍스트와 관련된 코드, 즉 outer 함수 내부의 코드들을 순차적으로 실행함.
4. outer 함수 내부에서 inner 함수가 호출 됨(2)
5. inner 함수의 실행 컨텍스트가 콜 스택의 가장 위에 담기면 outer 컨텍스트와 관련된 코드의 실행을 중단하고 inner 함수를 실행함.
-- 정리
1. 실행하는 순간 동일한 환경의 실행컨텍스트를 만들어서 전역 컨텍스트를 담게 됨
2. 코드들을 훑고 내려가면서 함수를 실행하는 코드를 만나면 실행컨텍스트에 담게 됨
ex) outer() (3번 줄)
3. 실행컨텍스트에 담긴 함수를 실행 하던 중 다시 다른 함수를 만나게 되면 지금 실행하던 함수(outer)의 실행을 중단하고 다른 함수(inner)를 실행컨텍스트 위에 담에 됨,
4. 다시 inner() 함수가 종료되면 outer() 함수를 중단 한 부분부터 다시 실행하고 중단하면 stack에서 제거함.
5. 모든 함수가 실행컨텍스트에서 제거되고 나면 전역 컨텍스트도 제거되고 콜 스택도 종료됨.
실행컨텍스트의 환경정보
어떤 실행 컨텍스트가 활성화될 때 자바스크립트 엔진은 해당 컨텍스트에 관련된 코드들을 실행하는 필요한 환경정보들을 수집해서 실행 컨텍스트 객체에 저장 함.
환경변수: 현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경정보, 선언 시점의 렉시컬환경의 스냅샷으로 변경 사항은 반영되지 않음
렉시컬환경 (어휘적환경): 처음에는 환경변수와 같지만 변경사항이 실시간으로 반영 됨,
# 환경변수
환경변수에 담기는 내용은 렉시컬 환경과 같지만 최초 실행 시의 스냅샷을 유지한다.
실행컨텍스트를 생성 할 때 환경변수에 정보를 먼저 담은 다음, 그대로 복사해서 렉시컬 환경을 만들고 이후에는 렉시컬 환경을 주로 활용함,
환경변수와 렉시컬 환경의 내부는 환경 레코드와 외부환경참조로 구성되어있음
(실행컨텍스트와 외부환경참조는 나중에 클로저를 이해하기 위한 기본개념이 될 수도 있다.)
# 환경레코드와 호이스팅
환경레코드에는 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장됨,
컨텍스트를 구성하는 함수에 지정된
1. 매개변수 식별자,
2. 선언한 함수가 있을 경우 그 함수 자체(함수),
3. var로 선언된 변수의 식별자(전역변수) 등이 식별자에 해당됨,
컨텍스트 내부 전체를 처음부터 끝까지 쭉 훑어나가며 순서대로 수집함
코드를 실행하기 전에 이미 변수 정보들을 수집을 마친 상태라서 코드는 실행전에도 해당 환경에 속한 코드의 변수명을 모두 알고 있는 상태가 됨
엔진의 실제 동작 방식대신 자바스크립트 엔진은 식별자들을 최상단으로 끌어올려놓은 다음 실제 코드를 실행한다. 라고 생각하더라도 코드를 해석하는데 문제가 없다. (호이스팅)
# 호이스팅 규칙과 함수 내부의 코드 실행 알아보기
환경레코드에는 매개변수의 이름, 함수 선언, 변수명 등이 담김
예)
예상 출력 1, undefined , 2
실제 출력 1, 1, 2
매개변수를 제외하고 생각하고 호이스팅 순서 정하기
var x = 1
var x
var x =2
위 코드의 선언부만 모두 끌어올린 상태
# 코드 실행
1. 02번째 x 변수 선언 -> 메모리에 저장 할 공간을 미리 확보하고 확보 한 공간의 주소 값을 변수 x에 연결
2. 03번쨰 줄과 4번째 줄: 다시 변수 x를 선언, 이미 선언된 변수 x가 있으므로 무시
3. 6번째 줄 x에 1을 할당함 우선 숫자 1을 별도의 데이터 영역 메모리에 담고, x와 연결 된 메모리 공간에 숫자 1을 가리키는 주소 값을 입력
4. 7번째 줄과 8번 째 줄: 각 x를 출력함 (1, 2)
5. 9번째 줄 x에 2를 할당함, 숫자 2를 별도의 1과 다른 메모리에 담고 그 주소 값을 x에 연결
6. 10번째 줄 x 를 출력하니 2가 출력
7. 함수 내부의 모든 코드가 실행 됐으므로 실행 컨텍스트가 콜스택에서 제거 됨
실행 결과: 1, 1, 2를 출력
# 다른예제)
예상결과 : undefined or error, bbb, function()
실행결과 : function, bbb, bbb
위 코드들은 var 변수이기 때문에 에러가 안나서 변수 선언 전에 출력해도 에러가 발생하지 않는 것임
# 함수 선언문과 함수 표현식
함수선언문은 function 정의부만 존재하고 별도의 할당 명령이 없는 것
function () {}
함수표현식은 function의 별도의 변수에 할당하는 것을 말함
let a = function() {}
함수표현식에도 익명과 기명으로 나뉘는데
다음과 같이 익명이 아닌 함수를 기명이라고 함
let a = function b() {}
b라는 함수명을 지어준다고 해도 a에 할당됬기 때문에 호출도 a로 해야함.
# 차이
함수 선언문은 호이스팅 대상이다.
함수 표현식은 호이스팅 되지않는다.
코드)
console.log(sum(1, 2)); // 3
console.log(sum2(1, 2)); // error
function sum(a, b) {
return a + b;
}
var sum2 = function (a, b) {
return a + b;
};
선언문인 sum 은 호이스팅 대상이 되어 함수 전체가 끌어올려지면서 console.log(sum(1,2))에도 3이 호출이 된다.
표현식은 선언부만 끌어올려지기 때문에 sum2 만 끌어올려지기 때문에 undefined 상태임
선언부만 끌어올려진 상태에서 console.log()로 함수를 실행하면 not function 라는 에러를 발생시키게 된다.
결국 호이스팅의 대상이 된다는 것은 잠재적 에러 대상이 될 가능성이 있다...
예시)
이미 sum 함수를 선언했는데
다시한번 sum 함수를 선언해서 로직이 바뀜
함수는 오버라이딩되면서 2번째 sum의 로직으로 동작하여
7 / 3을 출력하는 것이 아닌
11 / 5 을 출력하게 됨
# 함수표현식으로 수정
// console.log(sum(3, 4), "1"); // TypeError: sum is not a function
var sum = function (a, b) {
return a + b;
};
var a = sum(1, 2);
console.log(a, "1"); // 3
var sum = function (x, y) {
return x + y + y;
};
var c = sum(1, 2);
console.log(c, "2"); // 5
함수표현식으로 고칠 경우 선언 이전의 함수는 not function 에러를 발생시키고 오버라이딩이 안되는건 아니지만
a 는 바로 위의 sum 함수에 대한 결과 값만
c 도 마찬가지로 바로 위의 sum 함수에 대한 결과 값만 출력한다.
이유는 선언부만 끌어올려지고 할당과 console.log 는 원래의 자리에서 이루어지기 때문임.
'JavaScript' 카테고리의 다른 글
코어 this (0) | 2022.06.07 |
---|---|
코어 스코프, 스코프 체인, 외부환경참고 (0) | 2022.06.02 |
코어 - 불변객체, undefined, null (0) | 2022.05.24 |
코어 1 - 데이터 타입 (0) | 2022.05.24 |
JS 생성자 함수(1) 생성하기 (0) | 2021.09.13 |