JavaScript 완벽 가이드, ECMAScript 을 읽는 방법
ECMAScript 는 완벽한 자바스크립트 가이드입니다. ECMAScript 가 자바스크립트 언어를 정의한 문서이며 표준이기 때문입니다. 모든 자바스크립트 엔진은 표준인 ECMAScript 에서 요구하는 사항은 반드시 구현해야 합니다.
ECMAScript 를 읽고 싶어도 위 그림과 같이 특유의 단어와 문법으로 적혀 있어서 단순하게 읽을 수가 없습니다. 그래서 혹시 잘 정리한 문서가 있나 찾아봤지만 ECMAScript 에 추가된 새로운 기능을 소개하는 글만 있을 뿐, ECMAScript 를 구체적으로 설명하는 글을 찾을 수는 없었습니다. 그래서 제가 ECMAScript 을 읽다보니, 미리 알았으면 읽기 수월했을 개념들을 정리해서 글로 작성했습니다.
Language types
ECMAScript 에서 Language types 자바스크립트가 사용하는 타입을 의미합니다. 그래서 자바스크립트의 데이터 타입인 undefined
, Boolean
, Number
, String
, BigInt
, Symbol
과 Object
는 Language types 으로 분류되어 있습니다.
Specification Types
Specification Types 은 Language types 외에 ECMAScript 문서 내부에서만 사용하기 위한 타입입니다. ECMAScript 내부에서 기능을 설명하기 위한 용도로 만들어진 타입입니다. 따라서 자바스크립트에서는 직접적으로 사용할 수 없으며, 자바스크립트 엔진에 따라 실질적인 구현이 달라질 수 있습니다. Specification Types 의 대표적인 타입으로는 Reference
, Completion Record
, Property Descriptor
등이 있습니다.
Abstract Operations
Abstract Operations 는 ECMAScript 문서에 정의된 함수입니다.
위 그림처럼 Abstract Operations 은 개발자에게 익숙한 함수 선언문과 동일한 형식으로 작성되어 있습니다.
Internal Methods and Internal Slots
Abstract Operations 중 [[함수명]](변수)
형식으로 적힌 Abstract Operations 는 Internal Methods 입니다. Internal Methods 는 ECMAScript 내에서 동작을 설명하기 위한 개념일 뿐이라 자바스트립트에서 접근할 수 없습니다. ECMAScript 내부에서만 사용하는 Abstract Operation 입니다.
예를 들어 [[GetOwnProperty]](P)
는 [[함수명]](변수)
형태이기 때문에 Internal method 입니다. [[GetOwnProperty]](P)
는 Internal method 이기 때문에 ECMAScript 문서에는 정의되어 있지만, MDN API 문서 에서는 찾을 수 없습니다.
Internal Methods 만이 아니라 Internal Slots 이라는 개념도 있습니다. Internal Slots 는 Internal Methods 와 비슷하게 [[속성명]]
형식으로 정의되어 있습니다. Internal Slots 은 Object 의 상태 또는 속성을 설명하기 위한 개념입니다. Internal Methods 와 마찬가지로 자바스크립트에서 접근할 수 없습니다.
Internal Methods 와 Internal Slots 은 ECMAScript 의 정의를 설명하기 위한 개념이기 때문에 자바스크립트 엔진은 ECMAScript 에 정의된 Internal Methods 와 Internal Slots 을 동일한 이름의 함수 또는 클래스로 정의하지 않아도 됩니다. 심지어 구현할지 말지 조차 자바스크립트 엔진이 결정합니다. 자바스크립트 엔진은 ECMAScript 에 정의된 개념과 절차대로만 동작하도록 구현할 뿐입니다. 따라서 ECMAScript 에서는 하나의 Internal Methods 로 정의되어 있지만 자바스크립트 엔진에 따라 구현이 없을 수도 있고 다르게 구현될 수도 있습니다.
'Ordinary' Object vs 'Exotic' Object
ECMAScript 문서에서 말하는 Ordinary Object 는 'essential internal methods' 를 Object 의 공통된 정의대로 구현한 Obejct 를 의미합니다.
구체적으로 Ordinary Object 를 설명하자면, Ordinary Object 는 [[Prototype]]
이라는 internal slot 을 가져야 하며, [[Prototype]]
의 데이터 값은 null
이거나 상속을 위한 Object
여야 합니다. 그리고 Boolean
값인 [[Extensible]]
은 Object 가 확장 가능한지를 표현하는 internal slot 으로 모든 Ordinary Object 는 동일한 internal slot 을 가집니다. 그리고 모든 Object 는 아래 표와 같은 Essential Internal Methods 를 가집니다.
Internal Method | Signature |
[[GetPrototypeOf]] | ( ) → Object | Null |
[[SetPrototypeOf]] | (Object | Null) → Boolean |
[[IsExtensible]] | ( ) → Boolean |
[[PreventExtensions]] | ( ) → Boolean |
[[GetOwnProperty]] | (propertyKey) → Undefined | Property Descriptor |
[[DefineOwnProperty]] | (propertyKey, PropertyDescriptor) → Boolean |
[[HasProperty]] | (propetyKey) → Boolean |
[[Get]] | (propertyKey, Receiver) → any |
[[Set]] | (propertyKey, value, Receiver) → Boolean |
[[Delete]] | (propetyKey) → Boolean |
[[OwnPropertyKeys]] | ( ) → List of propertyKey |
Exotic Object 는 Ordinary Object 가 아닌 Object 입니다. Object 이기 때문에 위 표와 같은 Essential Internal Methods 가지고 있습니다. 하지만 Essential Internal Methods 가 일반적인 정의와는 다른 방식으로 동작합니다. 대표적인 Exotic Object 로는 Array
가 있습니다. 자바스크립트에서 Array
는 다른 언어의 배열과는 다르게 동작하며 일반적인 배열의 동작을 흉내내는 Object 입니다. 따라서 Array 는 일반적이지 않고 특수한 Object 입니다.
Completion Records
Specification Types 중 하나인 Completion Records 는 Abstract Operations 가 끝날 때 반환하는 데이터 집합입니다. ECMAScript 에 정의된 모든 함수는 암묵적으로 Completion Records 를 반환합니다. 예를 들어 Abstract Operations 에 정의된 절차 중 다음과 같이 Completion Records 가 아닌듯이 반환한다고 하더라도, Completion Records 를 반환하는 거라 생각하고 ECMAScript 를 읽어야 합니다.
Return "Infinity"
Return NormalCompletion("Infinity")
Abstract Operations 정의에 아무런 반환이 없더라도, 마지막에 Return NormalCompletion(undefined)
가 있다고 생각해야 합니다. 그리고 이 Completion Records 에 대한 ECMAScript 정의때문에 자바스크립트 함수에 return
문이 없어도 undefined
가 반환됩니다.
그런데 ECMAScript 를 편집하는 TC39 내부에서 Abstract Operations 가 암묵적으로 Completion Records 를 반환하는건 문제가 있다고 판단했는지 명시적으로 Completion Records 를 반환하도록 하는 작업을 진행하고 있는 듯합니다.
Completion Records 는 Record 타입이므로 다음과 표와 같은 데이터의 집합으로 이루어져 있습니다.
Name | Description |
[[Type]] | normal, break, continue, return, 또는 throw 중 하나의 데이터를 가집니다. normal 이 아닌 데이터는 모두 함수를 강제로 중단시켰음을 의미하는 데이터입니다. |
[[Value]] | 함수가 완료되었을 때 생성된 데이터를 가집니다. 예를 들어 반환값이나 예외가 발생했을 때 예외에 대한 데이터를 가집니다. |
[[Target]] | 만약 [[Type]] 이 break 또는 continue 일 때 어디서 중단되었는지를 나타내는 label 데이터를 가집니다. |
ReturnIfAbrupt(argument)
ECMAScript 의 Abstract Operations 에 자주 등장하는 물음표 ? 와 느낌표 ! 는 ReturnIfAbrupt(argument) 를 짧게 표현한 문법입니다.
ReturnIfAbrupt(argument) 은 ECMAScript 에 정의된 Abstract Operations 중 하나입니다. argument 로 제공된 Completion Record 의 [[Type]]
값을 검사해서 normal 이면 Completion Record 의 [[Value]]
를 반환하고, 만약 Completion Record 의 [[Type]]
값이 normal 이 아니면 argument 를 반환합니다.
ECMAScript 에서는 아래와 같은 패턴으로 자주 등장하니, ECMAScript 를 읽기 위해서는 반드시 알아둬야 하는 개념입니다.
Let val be ! OperationName()
위의 패턴을 풀어쓰면 다음과 같이 됩니다.
Let val be OperationName().
Assert: val is never an abrupt completion.
If val is a Completion Record, set val to val.[[Value]].
마찬가지로,
? OperationName()
를 풀어서 쓰면 아래와 같이 됩니다.
ReturnIfAbrupt(OperationName())
ECMAScript 내부에서 자주 사용해서 알아둬야 하는 약어
O | Ordinary object |
P | Property key value |
V | language Value |
Desc | Property Descriptor |
참고
How to Read the ECMAScript Specification
Understanding the ECMAScript spec
'Develop > Frontend 가이드' 카테고리의 다른 글
[FE] HTTP/2 - HyperText Transfer Protocol (Version 2) 을 자세히 알아보자 (0) | 2021.04.13 |
---|---|
[FE] JavaScript 완벽 가이드, ECMAScript 를 읽는 방법 (2/2) (0) | 2021.04.03 |
[FE] 브라우저 렌더링 Browser rendering - 5단계 변경 'change' (4) | 2021.03.31 |
[FE] 브라우저 렌더링 Browser rendering - 4단계 페인팅 'paint' (0) | 2021.03.30 |
[FE] 브라우저 렌더링 Browser rendering - 3단계 레이아웃 'layout' (0) | 2021.03.27 |
꾸준히 노력하는 개발자 "김예건" 입니다.