자바스크립트 실행 순서
- 자바스크립트는 단일 스레드 언어(한 번에 하나의 작업만 처리)
- ㄴ이 작업들이 실행되는 흐름을 관리하는 공간이 콜 스택
- 함수를 호출하면 스택에 쌓임 => 함수 실행이 완료되면 스택에서 빠짐 => 스택이 비었으면 다음 작업 시작
실행 순서 흐름
- 전역 코드 실행
- 함수 호출
- 현재 실행 중 함수가 끝나면 그 함수가 스택에서 제거됨
- 콜 스택은 항상 "맨 위에 있는 것"부터 처리
Promise
- 자바스크립트는 비동기 작업을 처리하기 위해 프로미스라는 객체를 사용
핵심 메서드
- Promise 상태
- pending : 대기중
- fulfilled : 성공
- rejected : 실패
유틸 메서드
- Promise.all : 여러 비동기 작업를 동시에 실행하고, 전부 성공해야 결과 반환
- Promise.race : 가장 먼저 끝난 작업의 결과 반환
- Promise.allSettled : 성공/실패 상관없이 모든 작업의 상태를 배열로 반환
- Promise.any : 가장 먼저 성공한 Promise 반환
async / await
- promise를 동기코드처럼 보이게 작성할 수 있게 하는 문법
- 비동기 코드가 깔끔해지고 가독성이 좋아짐
- try/catch로 에러 처리도 쉬움
- async를 함수 앞에 붙이면 이 함수는 Promise를 반환한다는 뜻
- await는 프로미스의 결과를 기다려줌, async 함수 안에서만 사용할 수 있음
async function getData() {
try {
const res = await fetch('/api');
return await res.json();
} catch (e) {
console.error(e);
}
}
fetch
- 네트워크 요청을 보내기 위한 Web API
동작방식
- 비동기 Promise 반환
- 응답(Response) 객체를 줌
- 데이터는 res.json() 등으로 한 번 더 파싱해야 함
fetch('/api')
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err));
- async/await와 조합하면 더 깔끔
const data = await fetch('/api').then(r => r.json());
스코프(Scope)
- 변수에 접근할 수 있는 범위
- 전역 스코프 : 어디서나 접근가능
- 지역 스코프 : 함수/블록 내부에서만 접근 가능
- let, const => 블록 스코프
- var => 함수 스코프
실행 컨텍스트
- 자바스크립트가 코드를 실행할 때 필요한 정보 묶음
- 전역 실행 컨텍스트 / 함수 실행 컨텍스트
렉시컬 환경
- 변수와 함수가 저장되는 공간 + 스코프 규칙
- Environment Record => 실제 변수 저장 공간
- Outer Environment Reference => 바깥 스코프 참조
스코프 체인
- 변수를 찾을때,
- 현재 스코프
- 바깥 스코프
- 최종적으로 전역
- 이렇게 차례대로 올라가며 검색하는 구조
- =>이 구조 덕분에 내부 함수가 외부 변수를 접근할 수 있는 것
호이스팅
- 선언이 코드의 최상단으로 끌어올려진 것처럼 보이는 현상
- 실제로 끌어올리는것은 아님! 실행 컨텍스트 생성 단계에서 미리 변수와 함수를 등록해두기 때문에 발생하는 것
호이스팅 규칙
- var => 선언만 위로 올라감, 값은 안 올라감 => undefined
- let, const => 선언은 되지만 초기화되지 않아 접근 불가
- 함수 선언문 function(){} => 전체가 호이스팅됨
- 함수 표현식 const fn = () => {} => 변수 호이스팅만 => TDZ
프로토타입
- 자바스크립트는 프로토타입 기반 언어
- 객체는 다른 객체를 상속받을 수 있고, 그 연결 고리가 prototype
- 객체는 내부적으로 [[Prototype]](숨겨진 링크)를 가지고 있음 => 이 링크를 통해 부모 객체의 속성/메서드를 사용할 수 있음
- 함수는 자동으로 prototype 속성을 가지며, 이를 기반으로 새로운 객체가 만들어짐
객체에서 어떤 프로퍼티를 찾을 때
- 자기 자신 => 없으면
- 부모 객체(prototype) => 없으면
- 최상위 Object.prototype 까지 탐색하는 구조
=> 이걸 프로토타입 체인이라 함
function Person(name) {
this.name = name;
}
Person.prototype.sayHi = function() {
console.log(`Hi, I'm ${this.name}`);
};
const me = new Person('Mina');
me.sayHi(); // 프로토타입에서 가져온 메서드
프로퍼티 디스크립터
- 객체의 프로퍼티는 단순히 "이름:값"형태가 아니라 여러 설정값을 가진 데이터
- => 이 설정들을 담고 있는 정보가 프로퍼티 디스크립터
디스크립터 종류
1. 데이터프로퍼티
- value : 값
- writable : 값 변경 가능 여부
- enumerable: 반복문에 나오는지
- configurable: 삭제/재정의 가능 여부
2. 접근자 프로퍼티 (getter/setter)
- get() : 값 읽기
- set() : 값 쓰기
객체 보호(불변성)
- Object.preventExtensions() : 추가 ❌, 삭제 ⭕, 변경 ⭕
- Object.seal() : 추가 ❌ 삭제 ❌, 값 변경만 가능
- Object.freeze() : 추가 ❌ / 삭제 ❌ / 변경 ❌ → 완전 동결, 가장 엄격한 불변성, 단 1-depth만 막음(얕은 동결)
클로저(closure)
- 함수 내부에서 외부 스코프 변수를 계속 기억하고 접근할 수 있는 현상
- 외부 함수가 종료돼도 그 변수는 사라지지 않고 살아있음
- 너무 많이 사용하거나 깊게 중첩되면 메모리 점유가 늘어날 수 있음
function outer() {
let count = 0;
return function inner() {
count++;
console.log(count);
};
} // outer()는 이미 끝났지만, inner()가 count를 계속 기억하고 접근할 수 있음
const increase = outer();
increase(); // 1
increase(); // 2
This 바인딩
- 자바스크립트에서 this는 상황에 따라, 누가 호출했냐에 따라 동적으로 결정되는 겂
1. 누가 호출했는지에 따라 동적으로 결정됨
1) 기본 바인딩
- 그냥 단독 호출 => 전역 객체(Window)
- strict 모드에서는 undefined
function foo() {
console.log(this); // window or undefined(strict)
}
foo();
2) 암시적 바인딩
- 객체의 메서드로 호출되면 => 그 객체가 this
const user = {
name: "Mina",
show() {
console.log(this.name); // "Mina"
}
};
user.show(); // user가 호출자 → this = user
3) 명시적 바인딩
- call, apply, bind로 강제로 this 지정 가능
function greet() {
console.log(this.name);
}
greet.call({ name: "Tom" }); // "Tom"
4) new 바인딩
- 생성자 함수로 호출하면 → 새로 생성된 객체가 this
function Person(name) {
this.name = name;
}
const p = new Person("Mina"); // this = p
2. 정적 this 바인딩 : bind + 화살표 함수
this 정적(고정)으로 만들기
- 2-1) bind()로 this 강제 고정
- 2-2) 화살표 함수의 정적 this
'자바스크립트' 카테고리의 다른 글
| 자바스크립트 복습3 (0) | 2025.12.10 |
|---|---|
| 자바스크립트 복습2 (0) | 2025.12.09 |
| 자바스크립트 복습1 (0) | 2025.12.08 |
| [JS] 함수 참조, 함수 호출 (0) | 2024.10.29 |
| [JS]자바스크립트 동작 원리(실행 컨텍스트, 스코프, 이벤트루프) (2) | 2024.10.25 |