티스토리 뷰
https://poiemaweb.com/es6-block-scope
ES6의 변경점을 주제별로 작동 원리까지 포함해 작성한 좋은 글이 있었다.
let: 블록 레벨 스코프를 가짐
들어가기 전에: 배경지식 - 자바스크립트 실행 컨텍스트의 원리https://poiemaweb.com/js-execution-context
실행 컨텍스트: VO(변수객체), SC(스코프 체인), thisValue(this값)를 프로퍼티로 가지는 객체
전역 컨텍스트인 경우: VO -> GO(전역 객체): 전역 변수, 전역 함수를 프로퍼티로 가지는 객체
함수 컨텍스트인 경우: VO -> AO(활성 객체): arguments 객체, 지역 변수, 내부 함수를 프로퍼티로 가지는 객체
최초 진입점
1. 전역 객체 생성 (DOM, BOM, built-in object 등)
2. 전역 코드 진입
3. 전역 실행 컨텍스트 생성, 실행 컨텍스트 스택에 쌓임
실행 컨텍스트의 생성 과정
1. 스코프 체인 생성과 초기화
2. 변수 객체화 (Variable instantiation) 실행
변수 객체화: GO/AO 객체에 프로퍼티(key)와 값(value)을 set함
(1. parameter: arguments -> 2. 함수명: 함수 객체 -> 3. 변수명: undefined 값 순서로)
2 보충) 생성된 함수 객체는 [[Scopes]] 프로퍼티를 가짐: 값 = 현재 실행 컨텍스트의 스코프 체인 프로퍼티가 참조하고 있는 객체 (스코프 체인 자체)
3 보충) 변수 선언: 선언 단계 (VO에 변수를 등록) -> 초기화 단계 (등록된 변수를 메모리에 할당, undefined로 초기화) -> 할당 단계(undefined로 초기화된 변수에 실제값 할당)
var: 선언과 초기화 단계가 한번에 이루어짐
let: 초기화 단계는 변수 선언문에 도달했을 때 이루어짐 => 초기화 이전에 변수 접근하려고 하면 ReferenceError
// 호이스팅은 일어난다.
let foo = 1; // 전역 변수
{ //새로운 실행 컨텍스트 생성
//지역 변수 foo 선언됐지만 초기화되지 않음
console.log(foo); // ReferenceError: foo is not defined
let foo = 2; // 지역 변수 foo = undefined 초기화, 2 할당
}
3. this value 결정
함수 호출 패턴에 의해 결정 (cf: 전역 컨텍스트 -> GO)
이후 코드 실행
Symbol
https://poiemaweb.com/es6-symbol
7번째 데이터 타입: immutable, 원시 타입.
이름 충돌의 위험이 없는 유일한 객체의 프로퍼티 키를 만들기 위해 사용
let propName = Symbol("descripton for debug");
well-known symbol: 일종의 약속으로 쓰이는 특정 프로퍼티 (ex: symbol.iterator - 이터레이터 프로토콜 구현 여부 등)
Iteration & for .. of 문
https://poiemaweb.com/es6-iteration-for-of
이터레이션 프로토콜: 데이터 컬렉션을 순회하기 위한 프로토콜(for .. of 순회 Spread 등)
이터러블 프로토콜 + 이러레이터 프로토콜
이터러블(Iterable): 순회 가능한 자료구조. System.iterator 메소드를 구현하거나 상속한 객체
System.iterator는 이터레이터 객체를 반환함
이터레이터(Iterator): 이터러블 요소를 탐색하기 위한 포인터. next() 메서드를 가짐
next() 메서드를 호출하면 value, done 프로퍼티를 갖는 iterator result 객체를 반환
{
value: 해당 순회에서 만난 요소,
done: 모든 요소를 순회했는지 여부 (true면 for..of문 종료), done 프로퍼티를 생략하면 무한 수열 가능
}
Lazy evaluation: 데이터를 요청하기 전(next() 메소드가 호출되기 전)까지는 데이터를 생성하지 않음
제너레이터와 async/await
https://poiemaweb.com/es6-generator
제너레이터 함수는 일반 함수와 같이 함수의 코드 블록을 한 번에 실행하지 않고 함수 코드 블록의 실행을 일시 중지했다가 필요한 시점에 재시작할 수 있는 특수한 함수이다.
제너레이터 함수 정의: function* 사용, 하나 이상의 yield문
function* genFunc() {
yield 1;
yield 2;
yield 3;
}
const genObj = genFunc(); //제너레이터 함수를 호출하면 제너레이터 반환
console.log(genObj.next());
console.log(genObj.next());
console.log(genObj.next());
제너레이터 함수를 호출하면 제너레이터를 반환한다.
제너레이터는 이터러블이면서 이터레이터다.
next()
제너레이터 객체의 next() 메서드를 호출하면 처음 만나는 yield문까지 실행되고 중단(suspend)된다.
다시 next()메서드를 호출하면 중단된 위치에서 다시 실행이 시작하여 다음 만나는 yield문 혹은 함수의 끝까지 실행되고 다시 중단된다.
next()메서드는 { value: yield 문이 반환한 값, done: 함수 내의 모든 yield문이 실행되었는지 = 함수의 끝에 도달하였는지?} 객체를 반환한다.
async/await
제너레이터를 활용해 비동기 처리를 동기적으로 할 수 있게 만들어준다?
비동기의 장점을 살리는 건 아니고 비동기 처리가 끝날 때까지 기다렸다가 next()를 수행한다고 보면 되나?