
자바스크립트 코드가 실행되는 환경
= 함수 실행에 대한 세부 정보를 담고 있는 내부 데이터 구조
코드가 실행될 때마다 생성된다
✔️렉시컬 환경
코드가 어디서 실행되며 주변에 어떤 코드가 있는지를 의미
코드가 실행되는 환경 설정, 관리
변수, 함수, 객체 유효 범위 결정
this 바인딩 설정
✔️this 바인딩
this : 객체를 참조하는 키워드
Web에서의 this : window
Node에서의 this : 빈객체(node에서는 dom 관련된 객체가 없기에 다른 런타임)
함수 호출에 따른 this 바인딩
- 함수 선언식의 this : global 객체
항상 전역객체에 바인딩 되기에 apply, call, bind 메소드 사용해서 바인딩 해준다- this 동적으로 결정
화살표 함수(arrow function)에서의 this :- this 정적으로 결정
- 렉시컬 this : 언제나 상위 스코프 this 가르킨다
생성자 함수 사용할 때 this 바인딩 :- new연산자를 붙여서 객체 생성하는 함수
addEventListener 사용시 콜백함수 this :
this를 바인딩하여 객체 지향 프로그래밍을 쉽게 구현할 수 있다window(브라우저) 또는 global(Node.js)이 전역 실행 컨텍스트의 this가 된다eval() 함수가 실행될 때 생성됩니다.https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/eval
→ eval() 말고 function 사용 권장
// bad
function looseJsonParse(obj) {
return eval(obj);
}
console.log(looseJsonParse("{a:(4-1), b:function(){}, c:new Date()}"));
```
```jsx
// good
function looseJsonParse(obj) {
return Function('"use strict";return (' + obj + ")")();
}
console.log(looseJsonParse("{a:(4-1), b:function(){}, c:new Date()}"));
✔️eval()
인자로 받은 코드를 caller 권한으로 수행하는 위험한 함수
- 악의적인 코드 수행 결과 초래 가능
- JS인터프리터를 사용하기에 느리다
활성 객체(Activation Object, AO)라고 부르기도 한다this가 가리키는 객체를 정의한다window , global✔️메모리 구조(힙, 스택, 큐)
힙 : 트리 기반 자료구조, 최대값 & 최소값 찾기 위해 설계된 구조
전역적으로 엑세스 가능
스택 : 후입선출, 책더미와 같은 모양
빠른 액세스 가능
ex) 브라우저 뒤로가기
큐 : 선입선출, 대기줄과 같은 모양
ex) 작업 처리 대기열
현재 실행중인 서브루틴에 대한 정보들을 담아두는 스택 구조 메모리영역
실행 컨텍스트를 관리하는 자료구조(Stack)
setTimeout, Promise)과 결합하여 효과적으로 실행 흐름을 관리할 수 있다✔️동기 vs 비동기
동기 : 요청, 결과가 동시에 일어난다
순서에 맞춰 진행, 동시 처리 불가능
→ 직관적 간단 설계 가능
비동기 : 동시에 일어나지 않는다
처리 시간이 긴 작업으로 인한 thread block 없이 처리할 방법이 필요하다 = 자바스크립트는 긴 작업을 메인 스레드에서 처리하지 않는다
= 멀티 스레드에서 작업(백그라운드에서 처리되는 작업)
동시 처리 가능, 하지만 속도 저하
→ 복잡하지만 자원을 효율적으로 사용할 수 있다
콜백 함수 사용 : 비동기 작업이 완료되었을 때 메인스레드에서 실행할 함수
function infinite() {
infinite();
}
infinite(); // Maximum call stack size exceeded
function first() {
second();
console.log("첫 번째 함수 실행");
}
function second() {
third();
console.log("두 번째 함수 실행");
}
function third() {
console.log("세 번째 함수 실행");
}
first();
// 세 번째 함수 실행
// 두 번째 함수 실행
// 첫 번째 함수 실행
first() 실행 → first 컨텍스트가 스택에 추가second() 실행 → second 컨텍스트가 스택에 추가third() 실행 → third 컨텍스트가 스택에 추가third() 종료 → 스택에서 제거second() 종료 → 스택에서 제거first() 종료 → 스택에서 제거✔️스레드(Thread)
실제 작업하는 주체
메인 스레드 : 브라우저 사용자 이벤트 처리, 디스플레이 전송 페인팅, 대부분 코드 실행하는 데 사용
싱글 스레드
- 문맥 교환 작업을 요구하지 않는다
- 자원 접근에 대한 동기화를 신경쓰지 않아도 된다
- 프로그래밍 난이도가 쉽고 자원 소모 적다
- 블로킹 : 연산량이 많은 작업을 수행하면 다 끝날 때까지 아무 동작을 못한다
멀티 스레드- 블로킹 현상 극복 : 새로운 스레드 생성으로
스레드 1개로는 느리기에 멀티 스레드가 있으면 전반적인 성능, 브라우저 전체 성능 보존할 수 있다- 프로그래밍 난이도가 높다
- context switching으로 시간이 많이 소요된다
❗️JS는 싱글 스레드인데 callback 함수, 비동기 어떻게?
A. 멀티스레드인 척 한다(브라우저, Node 환경에서 처리)
Call Stack : 일단 제일 먼저 여기서 처리한다
기본적인 자바스크립트 싱글 스레드 작업 처리
Web APIs : Call Stack에서 처리 못하는 작업은 Web APIs로 넘어간다
자바스크립트 엔진이 아닌 브라우저에서 제공하는 runtime 환경
Dom Event, AJAX, setTimeout 처리
Task Queue(Callback queue는 Task queue 한 종류) : 비동기 처리된 callback 함수가 대기하는 queue
(매크로)태스크 큐 : 콜백함수 이벤트, 타이머, ajax 요청, dom이벤트 핸들러
실제 자료구조는 set으로 구현되어 있다
queue가 아니다
마이크로태스크 큐 : promise의 then(), catch() 메소드, queueMicrotask() 함수
태스트 큐보다 우선 호출된다
Event Loop : 자바스크립트 내 루프
Call Stack, Task Queue 지속적으로 모니터링
처리해야 할 테스트가 있으면 순차적으로 처리
처리해야 할 테스트가 없으면 잠든다
= 대기 중인 오래된 작업을 Call Stack으로 push
스크립트, 핸들러, 이벤트가 활성화 될 때만 돌아간다
https://developer.mozilla.org/ko/docs/Glossary/Thread
✔️큐(queue)
선입선출의 자료구조
대기열, 순서 리스트
변수를 참조할 때 스코프 계층 구조를 따라 올라가는 매커니즘
= 실행 컨텍스트가 변수나 함수를 찾을 때 참조하는 영역의 연결 리스트
각 실행 컨텍스트는 자신의 변수 객체(VO)와 부모 실행 컨텍스트의 VO를 참조한다
✔️스코프 : 변수가 접근할 수 있는 범위
var 사용 시 호이스팅(Hoisting)으로 인해 예기치 않은 결과 발생 가능하다console.log(x); // undefined
var x = 10;
| 개념 | 목적 | 장점 | 단점 |
|---|---|---|---|
| 실행 컨텍스트 | 코드 실행 환경 관리, this 바인딩 관리 | 코드 실행 흐름을 구조적으로 관리, 유효 범위 명확 | 실행 컨텍스트가 많아지면 메모리 사용 증가 |
| 콜 스택 | 함수 호출 및 실행 컨텍스트 추적 | 함수 실행 순서가 명확, 비동기 코드 처리 가능 | 너무 깊어지면 스택 오버플로우 발생 |
| 스코프 체인 | 변수 및 함수의 유효 범위 탐색 | 가독성 증가, 캡슐화 및 데이터 보호 | 스코프 깊어지면 성능 저하, 클로저로 인한 메모리 누수 |