ECMAScript는 호스트 환경 내에서 계산을 수행하고 계산 객체를 조작하기 위한 객체 지향 프로그래밍 언어입니다. 여기에서 정의하는 ECMAScript는 계산에 필요한 모든 기능을 자체적으로 제공하도록 설계되지 않았습니다. 실제로 이 명세에는 외부 데이터의 입력이나 계산 결과의 출력을 위한 규정이 없습니다. 대신 ECMAScript 프로그램의 계산 환경은 이 명세에 기술된 객체와 기타 기능뿐 아니라 특정 환경에 고유한 객체도 제공할 것으로 기대됩니다. 이러한 객체의 설명과 동작은 ECMAScript 프로그램에서 접근할 수 있는 특정 프로퍼티와 호출할 수 있는 특정 함수를 제공할 수 있다는 점을 명시하는 것 외에는 이 명세의 범위를 벗어납니다.
ECMAScript는 원래 스크립팅 언어로 사용하도록 설계되었으나, 현재는 범용 프로그래밍 언어로 널리 사용됩니다. 스크립팅 언어는 기존 시스템의 기능을 조작하고, 사용자 정의하고, 자동화하는 데 사용하는 프로그래밍 언어입니다. 이러한 시스템에서는 유용한 기능이 사용자 인터페이스를 통해 이미 제공되며, 스크립팅 언어는 해당 기능을 프로그램으로 제어할 수 있도록 노출하는 수단입니다. 이러한 방식으로 기존 시스템은 객체와 기능으로 구성된 호스트 환경을 제공하여 스크립팅 언어의 기능을 완성한다고 할 수 있습니다. 스크립팅 언어는 전문 프로그래머와 비전문 프로그래머 모두가 사용하도록 설계됩니다.
ECMAScript는 원래 웹 스크립팅 언어로 설계되었으며, 브라우저의 웹 페이지를 동적으로 만들고 웹 기반 클라이언트-서버 아키텍처의 일부로 서버 계산을 수행하는 수단을 제공했습니다. 현재 ECMAScript는 다양한 호스트 환경에 핵심 스크립팅 기능을 제공하는 데 사용됩니다. 따라서 이 문서에서는 특정 호스트 환경과 독립적으로 핵심 언어를 명시합니다.
ECMAScript의 사용은 단순한 스크립팅을 넘어섰으며, 현재는 다양한 환경과 규모에서 모든 범위의 프로그래밍 작업에 사용됩니다. ECMAScript의 사용이 확대됨에 따라 제공하는 기능도 함께 확장되었습니다. ECMAScript는 이제 완전한 기능을 갖춘 범용 프로그래밍 언어입니다.
4.1 웹 스크립팅
웹 브라우저는 클라이언트 측 계산을 위한 ECMAScript 호스트 환경을 제공하며, 여기에는 창, 메뉴, 팝업, 대화 상자, 텍스트 영역, 앵커, 프레임, 방문 기록, 쿠키 및 입출력을 나타내는 객체 등이 포함됩니다. 또한 호스트 환경은 포커스 변경, 페이지와 이미지의 로드, 언로드, 오류와 중단, 선택, 폼 제출 및 마우스 동작과 같은 이벤트에 스크립팅 코드를 연결하는 수단을 제공합니다. 스크립팅 코드는 HTML 내부에 나타나며, 표시되는 페이지는 사용자 인터페이스 요소와 고정되거나 계산된 텍스트 및 이미지의 조합입니다. 스크립팅 코드는 사용자 상호 작용에 반응하며, 주 프로그램이 필요하지 않습니다.
웹 서버는 서버 측 계산을 위한 별도의 호스트 환경을 제공하며, 여기에는 요청, 클라이언트 및 파일을 나타내는 객체와 데이터를 잠그고 공유하는 수단이 포함됩니다. 브라우저 측 스크립팅과 서버 측 스크립팅을 함께 사용하면 웹 기반 애플리케이션에 맞춤형 사용자 인터페이스를 제공하면서 클라이언트와 서버 사이에 계산을 분산할 수 있습니다.
ECMAScript를 지원하는 각 웹 브라우저와 서버는 자체 호스트 환경을 제공하여 ECMAScript 실행 환경을 완성합니다.
4.2 호스트와 구현체
ECMAScript를 호스트 환경에 통합하는 데 도움이 되도록 이 명세는 특정 기능(예: 추상 연산)의 정의 전체 또는 일부를 이 명세 외부의 주체에 위임합니다. 편집상 이 명세는 다음과 같은 종류의 위임을 구분합니다.
구현체는 부속서 D에 열거된 기능 또는 구현체 정의나 구현체 근사로 표시된 기능을 추가로 정의하는 외부 주체입니다. 비공식적인 용법에서 구현체는 특정 웹 브라우저와 같은 구체적인 결과물을 가리킵니다.
구현체 정의 기능은 추가적인 제한 없이 그 정의를 외부 주체에 위임하는 기능입니다. 이 명세는 특정 동작을 권장하지 않으며, 적합한 구현체는 이 명세에서 제시한 제약 내에서 자유롭게 동작을 선택할 수 있습니다.
구현체 근사 기능은 이상적인 동작을 권장하면서 그 정의를 외부 주체에 위임하는 기능입니다. 적합한 구현체는 이 명세에서 제시한 제약 내에서 자유롭게 동작을 선택할 수 있지만, 이상적인 동작에 근접하도록 노력하는 것이 권장됩니다. Math.exp와 같은 일부 수학 연산은 구현체 근사입니다.
호스트는 부속서 D에 나열된 기능을 추가로 정의하지만, 그 밖의 구현체 정의 또는 구현체 근사 기능은 추가로 정의하지 않는 외부 주체입니다. 비공식적인 용법에서 호스트는 모든 웹 브라우저의 집합과 같이 부속서 D를 통해 이 명세와 동일한 방식으로 연동하는 모든 구현체의 집합을 가리킵니다. 호스트는 WHATWG HTML(https://html.spec.whatwg.org/)과 같은 외부 명세인 경우가 많습니다. 다시 말해, 호스트 정의 기능은 외부 명세에서 추가로 정의되는 경우가 많습니다.
호스트 훅은 외부 주체가 전체 또는 일부를 정의하는 추상 연산입니다. 모든 호스트 훅은 부속서 D에 나열되어야 합니다. 호스트 훅은 적어도 다음 요구 사항을 준수해야 합니다:
호스트 정의 기능은 추가적인 제한 없이 그 정의를 외부 주체에 위임하며 부속서 D에 나열된 기능입니다. 호스트가 아닌 구현체도 호스트 정의 기능에 대한 정의를 제공할 수 있습니다.
호스트 환경은 모든 호스트 정의 기능에 대해 선택한 구체적인 정의의 조합입니다. 호스트 환경에는 일반적으로 입력을 얻고 출력을 제공할 수 있는 객체 또는 함수가 전역 객체의 호스트 정의 프로퍼티로 포함됩니다.
이 명세는 항상 가장 구체적인 용어를 사용하는 편집 관례를 따릅니다. 예를 들어 어떤 기능이 호스트 정의라면 이를 구현체 정의라고 지칭하지 않는 것이 좋습니다.
호스트와 구현체 모두 이 명세에 정의된 언어 타입, 명세 타입, 추상 연산, 문법 생성 규칙, 내재 객체 및 내재 심볼을 통해 이 명세와 연동할 수 있습니다.
4.3 ECMAScript 개요
다음은 ECMAScript에 대한 비공식적인 개요이며, 언어의 모든 부분을 설명하지는 않습니다. 이 개요는 표준 본문의 일부가 아닙니다.
ECMAScript는 객체 기반입니다. 기본적인 언어 기능과 호스트 기능은 객체를 통해 제공되며, ECMAScript 프로그램은 서로 통신하는 객체들의 집합입니다. ECMAScript에서 객체는 0개 이상의 프로퍼티로 구성되며, 각 프로퍼티에는 사용 방법을 결정하는 속성이 있습니다. 예를 들어 프로퍼티의 Writable 속성이 false로 설정되면 실행 중인 ECMAScript 코드가 해당 프로퍼티에 다른 값을 할당하려는 모든 시도는 실패합니다. 프로퍼티는 다른 객체, 원시값 또는 함수를 담는 컨테이너입니다. 원시값은 다음 내장 타입 중 하나의 구성원입니다: Undefined, Null, Boolean, Number, BigInt, String, Symbol; 객체는 내장 타입 Object의 구성원이며, 함수는 호출 가능한 객체입니다. 프로퍼티를 통해 객체와 연결된 함수는 메서드라고 합니다.
ECMAScript는 ECMAScript 개체의 정의를 완성하는 내장 객체의 집합을 정의합니다. 이러한 내장 객체에는 전역 객체; Object, Function, Boolean, Symbol 및 다양한 Error 객체를 포함하여 언어의 런타임 의미론에 기본이 되는 객체; Math, Number, Date를 포함하여 숫자 값을 나타내고 조작하는 객체; 텍스트 처리 객체인 String과 RegExp; Array 및 요소가 각각 특정 숫자 데이터 표현을 갖는 9가지 종류의 TypedArray를 포함하여 인덱스가 있는 값의 컬렉션인 객체; Map과 Set 객체를 포함하는 키 기반 컬렉션; JSON 객체, ArrayBuffer, SharedArrayBuffer, DataView를 포함하여 구조화된 데이터를 지원하는 객체; 제너레이터 함수와 Promise 객체를 포함하여 제어 추상화를 지원하는 객체; Proxy와 Reflect를 포함하는 리플렉션 객체가 있습니다.
ECMAScript는 내장 연산자의 집합도 정의합니다. ECMAScript 연산자에는 다양한 단항 연산, 곱셈 연산자, 덧셈 연산자, 비트 이동 연산자, 관계 연산자, 동등 연산자, 이항 비트 연산자, 이항 논리 연산자, 할당 연산자 및 쉼표 연산자가 포함됩니다.
대규모 ECMAScript 프로그램은 프로그램을 여러 개의 문 및 선언 시퀀스로 나눌 수 있게 하는 모듈을 통해 지원됩니다. 각 모듈은 자신이 사용하며 다른 모듈에서 제공해야 하는 선언과, 자신의 선언 중 다른 모듈이 사용할 수 있는 선언을 명시적으로 식별합니다.
ECMAScript 구문은 의도적으로 Java 구문과 유사하게 설계되었습니다. ECMAScript 구문은 사용하기 쉬운 스크립팅 언어로 활용할 수 있도록 제약이 완화되어 있습니다. 예를 들어 변수의 타입을 선언할 필요가 없으며, 프로퍼티에도 타입이 연결되지 않습니다. 또한 정의된 함수의 선언이 해당 함수를 호출하는 부분보다 소스 텍스트상 앞에 나타날 필요가 없습니다.
4.3.1 객체
ECMAScript에는 클래스 정의를 위한 구문이 포함되어 있지만, ECMAScript 객체는 C++, Smalltalk 또는 Java의 객체처럼 근본적으로 클래스 기반인 것은 아닙니다. 대신 객체는 리터럴 표기법이나 생성자 등 다양한 방법으로 생성할 수 있습니다. 생성자는 객체를 생성한 다음, 프로퍼티에 초기값을 할당하여 객체 전체 또는 일부를 초기화하는 코드를 실행합니다. 각 생성자는 프로토타입 기반 상속과 공유 프로퍼티를 구현하는 데 사용되는 "prototype"이라는 프로퍼티를 갖는 함수입니다. 객체는 new 표현식에서 생성자를 사용하여 생성합니다. 예를 들어 new Date(2009, 11)은 새 Date 객체를 생성합니다. new를 사용하지 않고 생성자를 호출했을 때의 결과는 생성자에 따라 달라집니다. 예를 들어 Date()는 객체 대신 현재 날짜와 시간의 문자열 표현을 생성합니다.
생성자로 생성한 모든 객체는 생성자의 "prototype" 프로퍼티 값에 대한 암묵적인 참조를 가지며, 이를 객체의 프로토타입이라고 합니다. 또한 프로토타입은 자신의 프로토타입에 대한 null이 아닌 암묵적인 참조를 가질 수 있으며, 이러한 참조가 계속 이어질 수 있습니다. 이를 프로토타입 체인이라고 합니다. 객체의 프로퍼티를 참조하면 프로토타입 체인에서 해당 이름의 프로퍼티를 포함하는 첫 번째 객체의 그 프로퍼티를 참조하게 됩니다. 다시 말해, 먼저 직접 언급된 객체에 해당 프로퍼티가 있는지 검사합니다. 그 객체에 해당 이름의 프로퍼티가 있으면 참조는 그 프로퍼티를 가리킵니다. 해당 이름의 프로퍼티가 없으면 다음으로 그 객체의 프로토타입을 검사하며, 이러한 과정이 계속됩니다.
그림 1: 객체/프로토타입 관계
클래스 기반 객체 지향 언어에서는 일반적으로 인스턴스가 상태를 갖고, 클래스가 메서드를 가지며, 구조와 동작만 상속됩니다. ECMAScript에서는 객체가 상태와 메서드를 가지며, 구조, 동작 및 상태가 모두 상속됩니다.
프로토타입에 있는 특정 프로퍼티를 직접 포함하지 않는 모든 객체는 해당 프로퍼티와 그 값을 공유합니다. 그림 1은 이를 보여 줍니다:
CF는 생성자이며 객체이기도 합니다. new 표현식을 사용하여 다섯 개의 객체 cf1, cf2, cf3, cf4, cf5를 생성했습니다. 각 객체에는 "q1"과 "q2"라는 프로퍼티가 있습니다. 점선은 암묵적인 프로토타입 관계를 나타냅니다. 예를 들어 cf3의 프로토타입은 CFp입니다. 생성자CF 자체에는 "P1"과 "P2"라는 두 개의 프로퍼티가 있으며, 이 프로퍼티는 CFp, cf1, cf2, cf3, cf4 또는 cf5에서 보이지 않습니다. CFp에 있는 "CFP1"이라는 프로퍼티는 cf1, cf2, cf3, cf4, cf5가 공유하지만 CF는 공유하지 않습니다. CFp의 암묵적인 프로토타입 체인에 있는 프로퍼티 중 이름이 "q1", "q2" 또는 "CFP1"이 아닌 프로퍼티도 마찬가지로 공유됩니다. CF와 CFp 사이에는 암묵적인 프로토타입 연결이 없다는 점에 유의하시기 바랍니다.
대부분의 클래스 기반 객체 언어와 달리, 프로퍼티에 값을 할당하여 객체에 프로퍼티를 동적으로 추가할 수 있습니다. 즉, 생성자가 생성된 객체의 모든 프로퍼티 또는 일부 프로퍼티의 이름을 지정하거나 값을 할당할 필요는 없습니다. 위 그림에서는 cf1, cf2, cf3, cf4, cf5를 위한 새로운 공유 프로퍼티를 CFp의 프로퍼티에 새 값을 할당하여 추가할 수 있습니다.
ECMAScript 객체는 본질적으로 클래스 기반이 아니지만, 생성자 함수, 프로토타입 객체 및 메서드의 공통 패턴을 바탕으로 클래스와 유사한 추상화를 정의하는 것이 편리한 경우가 많습니다. ECMAScript 내장 객체 자체도 이러한 클래스와 유사한 패턴을 따릅니다. ECMAScript 2015부터 ECMAScript 언어에는 프로그래머가 내장 객체에서 사용하는 것과 동일한 클래스 유사 추상화 패턴을 따르는 객체를 간결하게 정의할 수 있도록 하는 클래스 정의 구문이 포함됩니다.
4.3.2 ECMAScript의 엄격 변형
ECMAScript 언어는 일부 사용자가 언어에서 사용할 수 있는 특정 기능의 사용을 제한하기를 원할 수 있음을 인정합니다. 사용자는 보안을 위해, 오류를 유발하기 쉽다고 생각하는 기능을 피하기 위해, 강화된 오류 검사를 얻기 위해 또는 자신이 선택한 다른 이유로 이러한 제한을 원할 수 있습니다. 이를 지원하기 위해 ECMAScript는 언어의 엄격 변형을 정의합니다. 언어의 엄격 변형은 일반 ECMAScript 언어의 특정 구문적·의미적 기능을 제외하고 일부 기능의 세부 의미를 수정합니다. 또한 엄격 변형은 비엄격 형태의 언어에서 오류로 명시되지 않은 상황에 대해 오류 예외를 던져 보고해야 하는 추가 오류 조건을 명시합니다.
ECMAScript의 엄격 변형은 일반적으로 언어의 엄격 모드라고 합니다. 엄격 모드의 선택과 ECMAScript 엄격 모드 구문 및 의미의 사용은 11.2.2에 설명된 대로 개별 ECMAScript 소스 텍스트 단위 수준에서 명시적으로 이루어집니다. 엄격 모드는 구문적인 소스 텍스트 단위 수준에서 선택되므로, 해당 소스 텍스트 단위 내에서 국소적으로 영향을 미치는 제한만 부과합니다. 엄격 모드는 여러 소스 텍스트 단위에 걸쳐 일관되게 동작해야 하는 ECMAScript 의미론의 어떠한 측면도 제한하거나 수정하지 않습니다. 하나의 완전한 ECMAScript 프로그램은 엄격 모드와 비엄격 모드의 ECMAScript 소스 텍스트 단위로 함께 구성될 수 있습니다. 이 경우 엄격 모드는 엄격 모드 소스 텍스트 단위 내에 정의된 코드를 실제로 실행할 때만 적용됩니다.
이 명세에 적합하려면 ECMAScript 구현체는 이 명세에 정의된 제한 없는 전체 ECMAScript 언어와 ECMAScript 언어의 엄격 변형을 모두 구현해야 합니다. 또한 구현체는 제한 없는 소스 텍스트 단위와 엄격 모드 소스 텍스트 단위를 하나의 복합 프로그램으로 결합하는 것을 지원해야 합니다.
4.4 용어 및 정의
이 문서에서는 다음 용어와 정의를 적용합니다.
4.4.1 구현체 근사
구현체 근사 기능은 외부 주체가 전체 또는 일부를 정의하지만, 이 명세에서 이상적인 동작을 권장하는 기능입니다
생성자의 "prototype" 프로퍼티 값은 상속과 공유 프로퍼티를 구현하는 데 사용되는 프로토타입 객체입니다.
4.4.8 프로토타입
다른 객체에 공유 프로퍼티를 제공하는 객체입니다
참고
생성자가 객체를 생성하면 해당 객체는 프로퍼티 참조를 해석하기 위해 생성자의 "prototype" 프로퍼티를 암묵적으로 참조합니다. 생성자의 "prototype" 프로퍼티는 프로그램 표현식 constructor.prototype으로 참조할 수 있으며, 객체의 프로토타입에 추가된 프로퍼티는 상속을 통해 해당 프로토타입을 공유하는 모든 객체가 공유합니다. 또는 내장 함수 Object.create를 사용하여 명시적으로 지정한 프로토타입을 갖는 새 객체를 생성할 수 있습니다.
Boolean 객체는 new 표현식에서 Boolean 생성자를 사용하고 Boolean 값을 인수로 전달하여 생성합니다. 생성된 객체에는 해당 Boolean 값을 값으로 갖는 내부 슬롯이 있습니다. Boolean 객체는 Boolean 값으로 강제 변환할 수 있습니다.
4.4.20 String 값
0개 이상의 16비트 부호 없는 정숫값으로 이루어진 유한한 순서 있는 시퀀스인 원시값입니다
참고
String 값은 String 타입의 구성원입니다. 시퀀스의 각 정숫값은 일반적으로 UTF-16 텍스트의 단일 16비트 단위를 나타냅니다. 그러나 ECMAScript는 이러한 값이 16비트 부호 없는 정수여야 한다는 것 외에는 값에 어떠한 제한이나 요구 사항도 부과하지 않습니다.
String 객체는 new 표현식에서 String 생성자를 사용하고 String 값을 인수로 전달하여 생성합니다. 생성된 객체에는 해당 String 값을 값으로 갖는 내부 슬롯이 있습니다. String 생성자를 함수로 호출하여 String 객체를 String 값으로 강제 변환할 수 있습니다(22.1.1.1).
Number 객체는 new 표현식에서 Number 생성자를 사용하고 Number 값을 인수로 전달하여 생성합니다. 생성된 객체에는 해당 Number 값을 값으로 갖는 내부 슬롯이 있습니다. Number 생성자를 함수로 호출하여 Number 객체를 Number 값으로 강제 변환할 수 있습니다(21.1.1.1).