🌐 US-Proxy
class="h-entry status-LS">

인프라

현행 표준 — 마지막 업데이트

참여:
GitHub whatwg/infra (새 이슈, 오픈 이슈)
Matrix에서 채팅
커밋:
GitHub whatwg/infra/commits
이 커밋 기준 스냅샷
테스트:
web-platform-tests infra/ (진행 중 작업)
번역 (비공식):
日本語
简体中文
한국어

요약

인프라 표준은 표준이 구축되는 기본 개념을 정의하는 것을 목표로 합니다.

목표

더 많은 목표에 대한 제안도 환영합니다.

1. 사용법

X라는 제목의 문서에서 이 표준을 사용하려면 다음과 같이 합니다:

X는 인프라에 의존합니다. [Infra]

더불어, 모든 용어를 교차 참조하여 모호성을 피하는 것이 강력히 권장됩니다.

2. 관례

2.1. 적합성

모든 단언문, 다이어그램, 예시, 주석은 비규범적이며, 명시적으로 비규범적임이 표시된 모든 섹션 역시 비규범적입니다. 그 외의 모든 내용은 규범적입니다.

"MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", "OPTIONAL" 키워드는 RFC 2119에서 설명한 대로 해석해야 합니다. [RFC2119]

이러한 키워드는 소문자로 작성되어도 동일한 의미를 가지며, 비규범적 내용에서는 등장할 수 없습니다.

이는 RFC 8174를 의도적으로 위반하는 것으로, 가독성과 IETF 이외에서 출판된 RFC 8174 이전 문서들에서의 오랜 관행을 유지하기 위한 것입니다. [RFC8174]

위의 모든 내용은 이 표준 및 이 표준을 사용하는 모든 문서에 적용됩니다. 이 표준을 사용하는 문서는 "must", "must not", "should", "may"만을, 그리고 이를 소문자로 사용하는 것이 더 읽기 쉽기 때문에 권장합니다.

비규범적 내용에는 "strongly encouraged", "strongly discouraged", "encouraged", "discouraged", "can", "cannot", "could", "could not", "might", "might not" 등을 사용할 수 있습니다.

2.2. 다른 명세와의 준수

일반적으로, 명세는 다양한 다른 명세들과 상호작용하고 이에 의존합니다. 때로는 불행히도 상충되는 요구로 인해 어떤 명세가 다른 명세의 요구사항을 위반해야 하는 경우가 있습니다. 이런 경우, Infra 표준을 사용하는 문서에서는 그러한 위반을 의도적 위반으로 표기하고, 그 이유를 명시해야 합니다.

이전 섹션 § 2.1 적합성은 의도적 위반의 예시로, 인프라가 RFC 8174를 위반했음을 문서화합니다.

2.3. 용어

둘 다 포함하는 "or"(예: "width 또는 height가 0인 경우")와 둘 중 하나만을 의미하는 "or"가 모두 가능한 상황에서는, 명시적으로 "but not both"로 독점적임을 나타내지 않는 한, "or"는 포괄적 "또는"(즉, "둘 다 가능")로 해석합니다.


user agent는 사용자를 대신하여 동작하는 모든 소프트웨어 엔터티를 의미합니다. 예를 들어 웹 콘텐츠를 검색·렌더링하고 사용자 상호작용을 지원합니다. Infra 표준을 사용하는 명세에서, user agent는 일반적으로 해당 명세를 구현하는 클라이언트 소프트웨어의 인스턴스입니다. 클라이언트 소프트웨어 자체는 구현체로 불립니다. 한 사람은 여러 user agent를 사용할 수 있으며, 하나의 구현체를 여러 user agent로 동작하게 할 수도 있습니다. 예를 들어 여러 프로필 혹은 구현체의 프라이빗 브라우징 모드를 사용하는 경우입니다.

구현체 정의로 언급된 경우, 구현체 정의로 언급된 내용의 세부사항은 구현체에 달려 있습니다. 별도의 언급이 없다면, 그 반대로 구현체는 이 표준을 사용하는 문서에 정의된 규칙을 따라야 합니다.

input에 U+000A (LF) 코드를, 결과적으로 각 줄이 width 코드 포인트를 넘지 않도록 구현체 정의 방식으로 삽입합니다. 여기서 줄 구분은 input의 시작, 끝, 그리고 U+000A (LF)로 판단합니다.

2.4. 프라이버시 문제

Infra 표준을 사용하는 문서에 정의된 일부 기능은 사용자 편의성과 맞바꾸어 일정 수준의 프라이버시를 희생할 수 있습니다.

일반적으로 인터넷의 구조상, 사용자는 자신의 IP 주소로 식별될 수 있습니다. 하지만 IP 주소는 완벽하게 사용자를 식별하지 않습니다. 사용자가 장치나 네트워크를 옮기면 IP도 바뀌고, NAT 라우팅, 프록시 서버, 공용 컴퓨터 등으로 인해 하나의 IP에서 여러 사용자가 나올 수 있습니다. 또한 onion 라우팅 같은 기술로 요청을 더 익명화할 수 있습니다. [RFC791]

그러나 사용자의 요청을 서로 연결하는 데 IP 주소만이 유일한 수단은 아닙니다. 예를 들어 쿠키는 바로 이 목적을 위해 설계된 것이며, 대부분의 웹 세션 기능의 근간입니다. 더 일반적으로는, HSTS, HTTP 캐시, 연결 그룹화, Storage API 등 모든 종류의 캐시 혹은 공유 상태가 오용될 수 있습니다. [COOKIES] [RFC6797] [STORAGE]

더 미묘한 방법도 있습니다. 사용자의 시스템 특성 일부가 여러 사용자 그룹을 구분하는 데 쓰일 수 있습니다. 이런 정보가 충분히 모이면, 개별 사용자의 브라우저의 "디지털 지문"을 산출할 수 있으며, 이는 IP 주소보다도 더 확실하게 동일 사용자의 요청임을 판별할 수 있습니다.

이렇게 요청을 그룹화하는 것은 특히 여러 사이트에 걸쳐 악의적으로 사용될 수 있습니다. 예를 들어, 정부가 어떤 사람이 길찾기 서비스를 통해 알아본 주소(실제 거주지)와 포럼 사이트 활동(정치 성향)을 결합해 선거권을 제한하는 것 등이 있습니다.

악의적 목적이 매우 심각할 수 있으므로, user agent 구현자와 명세 작성자는 지문 채취나 추적에 쓰일 수 있는 정보 누출을 최소화하도록 적극 권장합니다.

하지만, 이 섹션 첫 문단에서 알 수 있듯, 때로는 지문 채취·추적에 악용될 수 있는 API를 열어주는 것이 상당한 이득이 되기도 하기에, 모든 누수를 막는 것은 불가능합니다. 예를 들어, 특정 계정으로 로그인하려면 요청이 모두 동일 사용자임을 식별할 수 있어야 합니다. 더 미묘하게는, 텍스트 너비 측정처럼 캔버스에 텍스트를 그리는 효과에 필요한 정보도 사용자의 폰트 설치 정보 등 지문 채취에 쓰일 수 있습니다.

(이것은 추적 벡터입니다.) Infra 표준을 사용하는 문서에서 정의된 기능 중 추적 벡터로 사용될 수 있는 항목에는 이 단락처럼 표시됩니다.

플랫폼의 다른 기능도 다음과 같이 동일한 목적으로 악용될 수 있습니다:

3. 알고리즘

3.1. 적합성

알고리즘과 알고리즘의 일부로 명령형으로 작성된 요구사항(예: "앞의 공백을 제거한다" 또는 "false를 반환한다")은 알고리즘이나 단계의 도입에 사용된 키워드(예: "must")의 의미대로 해석해야 합니다. 만약 그런 키워드가 없다면, must가 암묵적으로 적용됩니다.

예를 들어, 명세에 다음과 같이 쓰여 있다면:

오렌지를 먹는다는 것은 사용자가 다음을 해야 한다:

  1. 오렌지 껍질을 벗긴다.
  2. 오렌지 조각들을 분리한다.
  3. 오렌지 조각을 먹는다.

이는 다음과 동일합니다:

오렌지를 먹는다는 것은:

  1. 사용자는 오렌지 껍질을 벗겨야 한다.
  2. 사용자는 오렌지 조각을 분리해야 한다.
  3. 사용자는 오렌지 조각을 먹어야 한다.

여기서 핵심 키워드는 "must"입니다.

위 예시에서, 알고리즘이 단순히 "오렌지를 먹는다:"로만 도입되어도 동일하게 "must"가 암묵적으로 적용됩니다.

알고리즘 또는 구체적 단계로 작성된 적합성 요구사항은 결과가 동일하다면 어떤 방식으로든 구현할 수 있습니다. (특히, 알고리즘은 따라가기 쉽게 설계되었으며 성능을 목적으로 하지 않습니다.)

성능은 사용자 인식, 컴퓨터 아키텍처, 그리고 시간이 지남에 따라 흔해지는 입력 유형 등에 의해 영향을 받으므로 맞추기 어렵습니다. 예를 들어, JavaScript 엔진은 표준화된 단일 알고리즘에 대해 여러 코드 경로를 가질 수 있으며, 이는 속도나 메모리 최적화를 위해서입니다. 이러한 모든 코드 경로를 표준화하는 것은 현실적으로 불가능하며, 단일 알고리즘만큼 시간의 시험을 견디기도 어렵습니다. 따라서 성능은 경쟁의 영역으로 남겨두는 것이 가장 좋습니다.

3.2. 알고리즘 입력 제한 피하기

Infra 표준을 사용하는 문서는 일반적으로 알고리즘 입력의 크기, 자원 사용량 등과 관련한 특정 제한을 강제하지 않아야 합니다. 이는 user agent 간 경쟁을 가능하게 하고 미래의 컴퓨팅 요구를 제한하지 않기 위함입니다.

(이것은 추적 벡터입니다.) 그럼에도 불구하고, user agent는 제한되지 않은 입력에 대해 구현체 정의 제한을 둘 수 있습니다. 예를 들어, 서비스 거부 공격 방지, 메모리 부족 방지, 플랫폼 고유 제약 회피 등이 있습니다.

전역 자원 제한은 자원 고갈 공격의 변종을 통해 부채널로 악용될 수 있으며, 공격자가 피해 애플리케이션이 전역 제한에 도달했는지 관찰할 수 있습니다. 제한은 user agent의 고유성을 높이는 경우에만 지문 채취에도 쓰일 수 있습니다. 예를 들어, 하드웨어에 특화된 경우입니다.

메모리 내 비트맵을 생성할 수 있게 하는 API는 모든 크기를 허용하거나, JavaScript의 Number.MAX_SAFE_INTEGER와 같이 매우 큰 제한까지 허용할 수 있습니다. 하지만, 구현체는 실제로 구현체 정의(즉, 명세에 없는) 제한을 둘 수 있으며, 무한한 메모리 할당을 시도하지 않을 수 있습니다.

프로그래밍 언어가 최대 호출 스택 크기를 명세하지 않을 수도 있습니다. 하지만 구현체는 실질적 이유로 제한을 둘 수 있습니다.

특정 제한에 코드가 의존하게 될 수 있으므로, 상호운용성을 위해 제한을 정의하는 것이 유용할 수 있습니다. 때로는 이런 방식을 받아들이는 것이 미래에도 문제가 되지 않으며, 더 많은 user agent에서 코드를 실행할 수 있게 해줍니다.

또한 구현체 정의 제한에 하한을 두는 것도 유용할 수 있습니다. 즉, 모든 구현체가 일정 최소 크기의 입력을 처리할 수 있도록 보장하는 것입니다.

3.3. 선언

알고리즘 이름은 보통 동사구로 작성되지만, 때로는 독립적 존재를 강조하는 이름을 부여해 표준과 독자가 더 관용적으로 알고리즘을 참조할 수 있게 합니다.

후자의 예시로는 "attribute change steps", "internal module script graph fetching procedure", "overload resolution algorithm" 등이 있습니다.

알고리즘은 이름, 매개변수, 반환 타입을 아래와 같은 형식으로 선언합니다:

[알고리즘 이름]을 위해, [type1] [parameter1], [type2] [parameter2], …를 받아 다음 단계를 수행한다. 반환값은 [return type]이다.

(동사구가 아닌 알고리즘 이름에는 "To perform the [algorithm name]…"과 같이 씁니다. 더 복잡한 매개변수 선언은 § 3.4 매개변수 참고.)

멋진 포맷을 파싱한다 알고리즘은 byte sequence bytes를 받아 다음 단계를 수행한다. 반환값은 string 또는 null이다.

값을 반환하지 않는 알고리즘은 더 짧은 형식을 사용합니다. 반환 타입이 단계에서 명확히 유추된다면 반환값이 있는 경우에도 이 짧은 형식을 사용할 수 있습니다:

[알고리즘 이름]을 위해, [type1] [parameter1], [type2] [parameter2], …를 받는다:

멋진 포맷을 파싱한다 알고리즘은 byte sequence bytes를 받는다:

매우 짧은 알고리즘은 한 문장으로 선언 및 명세할 수 있습니다:

멋진 포맷을 파싱한다 알고리즘은 byte sequence bytes를 받아, bytes의 isomorphic decoding의 ASCII 대문자화 결과를 반환한다.

타입은 알고리즘 선언에서 포함하는 것이 좋으나, 매개변수명이 충분히 명확하거나 맥락상 명확하다면 생략할 수 있습니다. (예: 알고리즘이 다른 알고리즘의 단순 래퍼일 경우.)

클래식 스크립트를 로드한다 알고리즘은 url을 받아, 내부 스크립트 로딩 알고리즘에 url과 "classic"을 넘겨 그 결과를 반환한다.

3.4. 매개변수

알고리즘 매개변수는 일반적으로 § 3.3 선언에 기술된 방식처럼 순차적으로 나열됩니다. 다만, 좀 더 복잡한 경우도 있습니다.

알고리즘 매개변수는 선택적일 수 있으며, 이 경우 알고리즘 선언에서 명시적으로 선택적임을 표시하고, 필수가 아닌 매개변수 뒤에 나열해야 합니다. 기본값을 줄 수도 있고, 알고리즘 본문에서 인자가 제공됐는지 확인할 수도 있습니다. 구체적으로 다음과 같이 작성합니다:

… an optional [type] [parameter] …

… an optional [type] [parameter] (default [default value]) …

선택적 boolean 매개변수에는 반드시 기본값이 지정되어야 하며, 그 값은 false여야 합니다.

탐색한다 알고리즘은 리소스 resource에 대해, 선택적 문자열 navigationType과 선택적 불리언 exceptionsEnabled (기본값 false)를 받는다:

  1. …
  2. navigationType이 제공된 경우, navigationType으로 무언가를 수행한다.
  3. …

이런 선택적 위치 매개변수를 가지는 알고리즘을 호출할 때, 선택적 인자는 뒤에서부터 생략할 수 있습니다.

이전 예시 알고리즘의 호출부는 다음과 같을 수 있습니다:

하지만, 두 번째(navigationType) 인자는 생략한 채 세 번째(exceptionsEnabled) 인자에만 값을 제공하는 것은 불가능합니다. 또한 마지막 호출은 "true"가 "예외 허용"임을 이해하려면 알고리즘 선언까지 돌아가서 매개변수 순서를 세어야 하므로 가독성이 떨어집니다. 이 문제를 해결하는 방법은 아래에서 설명합니다!

위치 매개변수 대신 명명된 선택적 매개변수를 사용하면 호출부의 명확성과 유연성을 높일 수 있습니다. 이런 매개변수는 변수이자 정의로 마크업되며, 호출부에서 링크로 연결됩니다.

탐색한다 알고리즘은 리소스 resource, 선택적 문자열 navigationType과 선택적 불리언 exceptionsEnabled (기본값 false)를 받는다:

  1. …
  2. navigationType이 제공된 경우, navigationType으로 무언가를 수행한다.
  3. …

호출부는 다음과 같이 쓸 수 있습니다:

알고리즘 단계 내에서는 인자값이 매개변수 선언과 링크되지 않고 단순 변수 참조로 남는다는 점에 유의하세요. 호출부에서만 매개변수 선언에 링크합니다.

필수 명명 매개변수도 위와 같은 방식(변수이자 정의로 마크업, 호출부에서 링크)으로 사용할 수 있습니다. 이는 호출부의 명확성을 높여줍니다.

불리언 매개변수는 선택적 여부와 상관없이 위치 인자로 둘 때보다 이름을 명확히 하는 것이 훨씬 읽기 쉽습니다. 이에 대한 논의는 Boolean Trap의 함정을 참고하세요.

명확성 향상을 위한 또 다른 보완 기법으로는, 관련 값을 구조체로 묶어 매개변수로 넘기는 방법이 있습니다. 이는 동일한 값 집합이 여러 알고리즘의 입력으로 쓰일 때 특히 유용합니다.

3.5. 변수

변수는 "let"으로 선언하고 "set"으로 변경합니다.

list를 새로운 list로 둔다.

  1. value를 null로 둔다.

  2. input이 string이면, value를 input으로 설정한다.

  3. 그 외에는 value를 input의 UTF-8 디코딩 값으로 설정한다.

  4. Assert: value는 string이어야 한다.

activationTarget를 isActivationEvent가 true이고 target이 activation behavior를 가지면 target, 아니면 null로 둔다.

변수는 선언 전에 사용할 수 없습니다. 변수는 블록 범위를 가집니다. 변수는 하나의 알고리즘에서 한 번만 선언할 수 있습니다.

여러 변수에 튜플의 항목을 할당하는 데 다중 할당 구문을 사용할 수 있으며, 변수 이름을 U+0028 LEFT PARENTHESIS와 U+0029 RIGHT PARENTHESIS로 둘러싸고, 각 변수 이름을 U+002C (,)로 구분한다. 할당되는 변수의 수는 항목의 수와 달라서는 안 된다. 이 튜플 안에서.

  1. statusInstance를 status (200, `OK`)로 둔다.

  2. (status, statusMessage)를 statusInstance로 둔다.

status와 statusMessage에 할당하는 것은 인덱스 또는 이름을 이용해 tuple의 항목에 접근하는 두 단계로 쓸 수도 있습니다.

3.6. 제어 흐름

알고리즘의 제어 흐름에서 "return"이나 "throw"가 요구되면 해당 문장이 속한 알고리즘을 종료합니다. "Return"은 값을 호출자에게 넘기고, "Throw"는 호출자에게 값을 자동으로 다시 던져 호출자 알고리즘을 종료합니다. 산문으로 예외를 "catch"하여 다른 동작을 수행할 수도 있습니다.

3.7. 조건부 중단

특정 조건이 참이 되면 일련의 단계를 중단하는 것이 유용할 때가 있습니다.

이럴 때는, 주어진 일련의 단계가 특정 condition에 도달하면 중단된다고 명시합니다. 이는 각 단계 전마다 condition을 검사하는 단계를 추가하고, 참이면 남은 단계를 건너뛰는 것으로 해석해야 함을 의미합니다.

이런 알고리즘에서는 다음 단계를 중단 시로 표시할 수 있으며, 그러한 경우 앞선 단계가 중단 조건으로 건너뛰어졌다면 반드시 실행해야 합니다.

다음 알고리즘은

  1. result를 빈 list로 둔다.

  2. 다음 단계를 실행하되, 사용자가 "Cancel" 버튼을 누르면 중단한다:

    1. π의 처음 백만 자리를 계산해 result에 추가한다.

    2. e의 처음 백만 자리를 계산해 result에 추가한다.

    3. φ의 처음 백만 자리를 계산해 result에 추가한다.

  3. 중단 시 "Didn’t finish!"를 result에 추가한다.

는 더 장황한 다음 형태와 같습니다.

  1. result를 빈 list로 둔다.

  2. 사용자가 "Cancel" 버튼을 누르지 않았다면:

    1. π의 처음 백만 자리를 계산해 result에 추가한다.

    2. 사용자가 "Cancel" 버튼을 누르지 않았다면:

      1. e의 처음 백만 자리를 계산해 result에 추가한다.

      2. 사용자가 "Cancel" 버튼을 누르지 않았다면 φ의 처음 백만 자리를 계산해 result에 추가한다.

  3. 사용자가 "Cancel" 버튼을 눌렀다면 "Didn’t finish!"를 result에 추가한다.

이 구문을 사용할 때는, 구현체가 지정된 단계 중간에 condition을 평가해도 결과가 구분되지 않는 한 허용됩니다. 예를 들어, 위 예시에서 result가 계산 중에 변경되지 않는다면, user agent는 계산을 중단할 수 있습니다.

3.8. 조건문

조건문이 있는 알고리즘은 "if", "then", "otherwise" 키워드를 사용해야 합니다.

  1. value를 null로 둔다.

  2. input이 string이면, value를 input으로 설정한다.

  3. value를 반환한다.

"otherwise" 키워드가 사용되면, "then" 키워드는 생략합니다.

  1. value를 null로 둔다.

  2. input이 string이면, value를 input으로 설정한다.

  3. 그 외에는 value를 failure로 설정한다.

  4. value를 반환한다.

  1. value를 null로 둔다.

  2. input이 string이면, value를 input으로 설정한다.

  3. 그 외, input이 list of strings이면, value를 input[0]으로 설정한다.

  4. 그 외에는 TypeError를 throw한다.

  5. value를 반환한다.

3.9. 반복

조건이 충족될 때까지 일련의 단계를 반복하는 다양한 방법이 있습니다.

Infra 표준은 이에 대해 아직 완전하지 않습니다. 필요하다면 이슈를 등록해 주세요.

For each

list(파생형 포함) 및 map에 대해 정의된 방식과 같습니다.

While

조건이 충족되는 동안 일련의 단계를 반복하는 명령입니다.

condition이 "met"인 동안:

  1. …

반복의 흐름은 continue 또는 break 요구로 제어할 수 있습니다. Continue는 반복 내 남은 단계를 건너뛰고 다음 항목으로 진행합니다. 더 이상 항목이 없으면 반복이 종료됩니다. Break는 반복 내 남은 단계와 항목을 모두 건너뛰어 반복을 종료합니다.

example을 list « 1, 2, 3, 4 »로 둔다. 다음 산문은 operation을 1, 2, 3, 4에 각각 수행한다:

  1. 각 item에 대해 example에서:

    1. item에 operation을 수행한다.

다음 산문은 1, 2, 4에 operation을 수행하며, 3은 건너뜁니다.

  1. 각 item에 대해 example에서:

    1. item이 3이면 continue.
    2. item에 operation을 수행한다.

다음 산문은 1, 2에 operation을 수행하며, 3과 4는 건너뜁니다.

  1. 각 item에 대해 example에서:

    1. item이 3이면 break.
    2. item에 operation을 수행한다.

3.10. 단언문

가독성을 높이기 위해 알고리즘에 불변식을 명시하는 단언문을 추가할 수 있습니다. 이를 위해 "Assert:" 뒤에 반드시 참이어야 하는 문장을 작성합니다. 해당 문장이 거짓이 된다면, 이는 Infra 표준을 사용하는 문서에 문제가 있음을 의미하므로 보고 및 수정되어야 합니다.

이 문장은 항상 참이어야 하므로, 구현체에는 아무런 영향이 없습니다.

  1. x를 "Aperture Science"로 둔다.

  2. Assert: x는 "Aperture Science"이다.

3.11. 동일성과 동등성

값 a가 값 b와 동일합니다(또는 동일합니다)라는 것은 두 값이 같은 값인 경우를 말합니다. 원시 데이터 타입의 값에서는 이는 두 값의 내용이 같다는 뜻입니다. 예를 들어 두 문자열은 같은 시퀀스로 구성되어 있을 때 동일합니다. 이 시퀀스는 코드 단위로 구성됩니다. 그 밖의 데이터 타입의 값, 예를 들어 리스트, 맵 및 구조체의 경우에는 두 값이 같은 인스턴스라는 뜻입니다. 이러한 두 값은 별도로 생성되었다면 그 내용이 같더라도 서로 동일하지 않습니다.

데이터 타입에는 동등성이 있으며, 이는 해당 데이터 타입의 두 값을 받아 불리언을 반환하는 알고리즘입니다. 달리 정의되지 않는 한, 데이터 타입의 동등성은 두 값이 서로 동일하면 참을 반환하고, 그렇지 않으면 거짓을 반환합니다. 이 표준은 동등성을 리스트, 맵 및 튜플에 대해 다르게 정의합니다.

값 a가 값 b와 동등합니다(또는 동등합니다)라는 것은 값 b와 a가 b와 동일하거나, 또는 a 와 b가 같은 데이터 타입이고 그 데이터 타입의 동등성이 a 와 b가 주어졌을 때 참을 반환하는 경우를 말합니다.

키 값은 키로 구성된 예시 튜플이며, (하나의 문자열)과 하나의 값(숫자로 이루어진 리스트)으로 구성됩니다.

  1. original을 키 값 ("x", « 1, 2, 3, 4 »)으로 둡니다.

  2. alsoOriginal을 original로 둡니다.

  3. copy를 키 값 ("x", « 1, 2, 3, 4 »)으로 둡니다.

  4. 단언: original은 동일합니다 alsoOriginal과.

  5. 단언: original은 동일하지 않습니다 copy와.

  6. 단언: original은 동등합니다 copy와. 두 값의 키는 서로 동일하고 두 값의 값은 동등하기 때문입니다.

동등성은 리스트, 맵 및 튜플의 내용을 동등함을 사용해 비교하므로, 직접 또는 간접적으로 자신을 포함하는 값을 비교하는 것은 무한 루프를 일으킬 수 있으므로 피해야 합니다.

  1. a를 « »로 둡니다.

  2. a에 a를 추가합니다. a에.

  3. b를 « »로 둡니다.

  4. b에 b를 추가합니다. b에.

  5. a가 동등하다면 b와, 그러면 …

마지막 단계는 절대 끝나지 않습니다. a와 b는 서로 동일하지 않고 서로 같은 크기를 가지므로, 두 값이 동등한지 판별하려면 a[0]이 b[0]과 동등한지 판별해야 하는데, 이는 같은 질문입니다. a[0]은 동일합니다 a와, 그리고 b[0]은 동일합니다 b와.

4. 원시 데이터 타입

4.1. Null값

null 값은 값이 없음을 나타내는 데 사용됩니다. JavaScript의 null 값과 상호 교환하여 사용할 수 있습니다. [ECMA-262]

element를 null로 둔다.

input이 빈 문자열이면 null을 반환한다.

4.2. 불리언

불리언은 true 또는 false입니다.

elementSeen을 false로 둔다.

4.3. 숫자

숫자는 복잡합니다. 이슈 #87을 참고하세요. 향후 타입 및 수학 연산에 대한 안내를 보강할 예정입니다. 기여 환영!


8비트 부호 없는 정수는 0에서 255(0부터 28 − 1)까지의 정수입니다.

16비트 부호 없는 정수는 0에서 65535(0부터 216 − 1)까지의 정수입니다.

32비트 부호 없는 정수는 0에서 4294967295(0부터 232 − 1)까지의 정수입니다.

64비트 부호 없는 정수는 0에서 18446744073709551615(0부터 264 − 1)까지의 정수입니다.

128비트 부호 없는 정수는 0에서 340282366920938463463374607431768211455(0부터 2128 − 1)까지의 정수입니다.

IPv6 주소는 128비트 부호 없는 정수입니다.


8비트 부호 있는 정수는 −128에서 127(−27에서 27 − 1)까지의 정수입니다.

16비트 부호 있는 정수는 −32768에서 32767(−215에서 215 − 1)까지의 정수입니다.

32비트 부호 있는 정수는 −2147483648에서 2147483647(−231에서 231 − 1)까지의 정수입니다.

64비트 부호 있는 정수는 −9223372036854775808에서 9223372036854775807(−263에서 263 − 1)까지의 정수입니다.


두 수가 같은 수학적 값이면 서로 동일합니다. 같은 수학적 값입니다.

4.4. 바이트

바이트는 8비트의 시퀀스로, "0x" 뒤에 두 자리 ASCII 대문자 16진수가 붙은 형식(0x00~0xFF)입니다. 바이트의 값은 실제 숫자입니다.

0x40은 바이트이며, 값은 64입니다.

ASCII 바이트는 0x00(NUL)에서 0x7F(DEL)까지의 바이트입니다. 0x28, 0x29를 제외한 ASCII 바이트는 ASCII format for Network Interchange의 Standard Code 섹션에 설명된 표기(괄호로 둘러싼 형식)가 뒤따를 수 있습니다. [RFC20]

0x28 뒤에는 "(left parenthesis)", 0x29 뒤에는 "(right parenthesis)"가 올 수 있습니다.

0x49 (I)는 UTF-8로 디코딩 시 코드 포인트 U+0049 (I)로 변환됩니다.

4.5. 바이트 시퀀스

바이트 시퀀스는 바이트의 시퀀스이며, 공백으로 구분된 바이트 시퀀스로 표현됩니다. 0x20 (SP)부터 0x7E (~)까지의 범위(양 끝 포함)에 있는 바이트로 이루어진 바이트 시퀀스는 실제 문자열과 혼동되는 것을 피하기 위해 따옴표 대신 백틱을 사용하여 문자열로 나타낼 수도 있습니다.

0x48 0x49는 `HI`로도 표현할 수 있습니다.

`Content-Type`과 같은 헤더는 바이트 시퀀스입니다.

문자열에서 바이트 시퀀스를 얻으려면 UTF-8 인코딩을 Encoding에서 사용하는 것이 권장됩니다. 드문 경우에는 동형 인코딩이 필요할 수도 있습니다. [ENCODING]

바이트 시퀀스의 길이는 이 시퀀스에 포함된 바이트의 수입니다.

바이트 시퀀스를 바이트 소문자화하려면, 그 시퀀스에 포함된 0x41 (A)부터 0x5A (Z)까지의 범위(양 끝 포함)에 있는 각 바이트를 0x20만큼 증가시킵니다.

바이트 시퀀스를 바이트 대문자화하려면, 그 시퀀스에 포함된 0x61 (a)부터 0x7A (z)까지의 범위(양 끝 포함)에 있는 각 바이트에서 0x20을 뺍니다.

바이트 시퀀스 A는 바이트 시퀀스 B에 대한 바이트 대소문자를 구분하지 않는 일치입니다. 이는 A를 바이트 소문자화한 결과가 B를 바이트 소문자화한 결과와 같은 경우입니다.

두 바이트 시퀀스가 동일한 것은 서로 동일한 바이트 시퀀스로 구성된 경우입니다.


바이트 시퀀스 potentialPrefix는 다음 단계가 true를 반환하는 경우 바이트 시퀀스 input의 접두사입니다:

  1. i를 0으로 둡니다.

  2. 다음을 true인 동안 반복합니다:

    1. i가 potentialPrefix의 길이보다 크거나 같으면 true를 반환합니다.

    2. i가 input의 길이보다 크거나 같으면 false를 반환합니다.

    3. potentialPrefixByte를 potentialPrefix의 i번째 바이트로 둡니다.

    4. inputByte를 input의 i번째 바이트로 둡니다.

    5. potentialPrefixByte가 inputByte가 아니면 false를 반환합니다.

    6. i를 i + 1로 설정합니다.

"input이 potentialPrefix로 시작합니다"는 "potentialPrefix가 input의 접두사입니다"와 같은 의미로 사용할 수 있습니다.

바이트 시퀀스 a는 다음 단계가 true를 반환하는 경우 바이트 시퀀스 b보다 바이트 기준으로 작습니다:

  1. b가 a의 접두사이면 false를 반환합니다.

  2. a가 b의 접두사이면 true를 반환합니다.

  3. a의 n번째 바이트가 b의 n번째 바이트와 다른 가장 작은 인덱스를 n으로 둡니다. (어느 바이트 시퀀스도 다른 시퀀스의 접두사가 아니므로 이러한 인덱스가 반드시 존재합니다.)

  4. a의 n번째 바이트가 b의 n번째 바이트보다 작으면 true를 반환합니다.

  5. false를 반환합니다.


바이트 시퀀스 input을 동형 디코딩하려면, 문자열을 반환합니다. 이 문자열의 코드 포인트 길이는 input의 길이와 같고, 그 코드 포인트의 값은 input의 바이트의 값과 동일한 순서로 같습니다.

4.6. 코드 포인트

코드 포인트는 유니코드 코드 포인트이며, "U+" 뒤에 네 자리에서 여섯 자리 ASCII 대문자 16진수로 표기합니다. 범위는 U+0000에서 U+10FFFF까지 포함됩니다. 코드 포인트의 값은 그 내부 숫자 값입니다.

코드 포인트 뒤에는 이름이나, U+0028 또는 U+0029가 아닐 때 괄호 안에 렌더링된 형태, 또는 둘 다를 표기할 수 있습니다. Infra 표준을 사용하는 문서는 코드 포인트가 렌더링이 불가능하거나 U+0028, U+0029인 경우 이름으로, 그렇지 않으면 괄호 안에 렌더링된 형태로 표기하는 것이 가독성에 좋으므로 이를 권장합니다.

코드 포인트의 이름은 Unicode에서 정의되며, ASCII 대문자로 표기합니다. [UNICODE]

🤔로 렌더링되는 코드 포인트는 U+1F914로 표기됩니다.

이 코드 포인트를 언급할 때 "U+1F914 (🤔)"처럼 추가 정보를 제공할 수 있습니다. 문서에서는 "U+1F914 THINKING FACE (🤔)"와 같이 사용할 수도 있지만, 이는 다소 장황합니다.

렌더링이 어려운 코드 포인트(예: U+000A)는 "U+000A LF"로 표기할 수 있습니다. U+0029는 괄호 불일치 방지를 위해 "U+0029 RIGHT PARENTHESIS"로 쓸 수 있습니다.

코드 포인트는 때로 문자로 불리거나, 상황에 따라 "U+" 대신 "0x"로 접두사를 붙이기도 합니다.

선행 서러게이트는 U+D800에서 U+DBFF 범위의 코드 포인트입니다.

후행 서러게이트는 U+DC00에서 U+DFFF 범위의 코드 포인트입니다.

서러게이트는 선행 서러게이트 또는 후행 서러게이트입니다.

스칼라 값은 서러게이트가 아닌 코드 포인트입니다.

비문자는 U+FDD0~U+FDEF, U+FFFE, U+FFFF, U+1FFFE, U+1FFFF, U+2FFFE, U+2FFFF, U+3FFFE, U+3FFFF, U+4FFFE, U+4FFFF, U+5FFFE, U+5FFFF, U+6FFFE, U+6FFFF, U+7FFFE, U+7FFFF, U+8FFFE, U+8FFFF, U+9FFFE, U+9FFFF, U+AFFFE, U+AFFFF, U+BFFFE, U+BFFFF, U+CFFFE, U+CFFFF, U+DFFFE, U+DFFFF, U+EFFFE, U+EFFFF, U+FFFFE, U+FFFFF, U+10FFFE, U+10FFFF에 해당하는 코드 포인트입니다.

ASCII 코드 포인트는 U+0000(NULL)~U+007F(DELETE) 범위의 코드 포인트입니다.

ASCII 탭 또는 줄바꿈은 U+0009 TAB, U+000A LF, U+000D CR입니다.

ASCII 공백은 U+0009 TAB, U+000A LF, U+000C FF, U+000D CR, U+0020 SPACE입니다.

"Whitespace"는 물질명사입니다.

XML, JSON, HTTP 일부 명세에서는 U+000C FF를 공백 정의에서 제외합니다:

새 기능에는 Infra의 ASCII 공백 정의 사용을 권장합니다. 단, 명세가 XML/JSON/HTTP만을 다룬다면 예외입니다.

C0 제어문자는 U+0000(NULL)~U+001F(INFORMATION SEPARATOR ONE) 범위의 코드 포인트입니다.

C0 제어문자 또는 공백은 C0 제어문자 또는 U+0020 SPACE입니다.

제어문자는 C0 제어문자 또는 U+007F(DELETE)~U+009F(APPLICATION PROGRAM COMMAND) 범위의 코드 포인트입니다.

ASCII 숫자는 U+0030(0)~U+0039(9) 범위의 코드 포인트입니다.

ASCII 대문자 16진수는 ASCII 숫자 또는 U+0041(A)~U+0046(F) 범위의 코드 포인트입니다.

ASCII 소문자 16진수는 ASCII 숫자 또는 U+0061(a)~U+0066(f) 범위의 코드 포인트입니다.

ASCII 16진수는 ASCII 대문자 16진수 또는 ASCII 소문자 16진수입니다.

ASCII 대문자 알파벳은 U+0041(A)~U+005A(Z) 범위의 코드 포인트입니다.

ASCII 소문자 알파벳은 U+0061(a)~U+007A(z) 범위의 코드 포인트입니다.

ASCII 알파벳은 ASCII 대문자 알파벳 또는 ASCII 소문자 알파벳입니다.

ASCII 영숫자는 ASCII 숫자 또는 ASCII 알파벳입니다.

4.7. 문자열

문자열은 16비트 부호 없는 정수의 시퀀스이며, 코드 단위라고도 합니다. 문자열은 JavaScript 문자열이라고도 합니다. 문자열은 큰따옴표와 고정폭 글꼴로 나타냅니다.

"Hello, world!"는 문자열입니다.

이는 Unicode가 "코드 단위"를 정의하는 방식과 다릅니다. 특히 여기서는 Unicode가 Unicode 16비트 문자열에 대해 정의하는 방식만을 가리킵니다. [UNICODE]

문자열은 또한 JavaScript 명세의 문자열 타입 절에 정의된 변환에 따라 코드 포인트를 포함하는 것으로 해석할 수도 있습니다. [ECMA-262]

이 변환 과정은 서로게이트 쌍을 해당 스칼라 값으로 변환하고, 남아 있는 서로게이트를 해당 코드 포인트에 매핑하여 실질적으로 그대로 둡니다.

코드 단위 0xD83D, 0xDCA9 및 0xD800으로 구성된 문자열을 코드 단위가 아닌 코드 포인트를 포함하는 것으로 해석하면, 코드 포인트 U+1F4A9 및 U+D800으로 구성됩니다.

문자열의 길이는 문자열에 포함된 코드 단위의 수입니다.

문자열의 코드 포인트 길이는 문자열에 포함된 코드 포인트의 수입니다.


포함할 수 있는 코드 포인트에 추가적인 제한이 있는 문자열을 나타내기 위해 이 명세에서는 ASCII 문자열, 동형 문자열 및 스칼라 값 문자열을 정의합니다. 이를 사용하면 명세가 더 명확해집니다.

ASCII 문자열은 모든 코드 포인트가 ASCII 코드 포인트인 문자열입니다.

동형 문자열은 모든 코드 포인트가 U+0000 NULL부터 U+00FF (ÿ)까지의 범위(양 끝 포함)에 있는 문자열입니다.

스칼라 값 문자열은 모든 코드 포인트가 스칼라 값인 문자열입니다.

스칼라 값 문자열은 모든 종류의 I/O 또는 UTF-8 인코딩이 관여하는 다른 종류의 작업에서 유용합니다.


문자열을 스칼라 값 문자열로 변환하려면, 모든 서로게이트를 U+FFFD (�)로 바꿉니다.

문자열을 코드 포인트를 포함하는 것으로 해석하는 과정에서 서로게이트 쌍은 이미 스칼라 값으로 변환되므로, 바뀌는 서로게이트는 서로게이트 쌍의 일부가 아닙니다.

모든 스칼라 값 문자열은 문자열이므로 스칼라 값 문자열은 언제나 문자열로 암시적으로 사용할 수 있습니다. 반면 문자열은 서로게이트를 포함하지 않는다고 알려진 경우에만 스칼라 값 문자열로 암시적으로 사용할 수 있으며, 그렇지 않으면 변환을 수행해야 합니다.

구현체가 실제로 문자열과 스칼라 값 문자열을 어떻게 표현하게 되는지에 따라 명시적인 변환을 수행해야 할 가능성이 높습니다. 성능과 메모리상의 이유로 구현체가 문자열만 해도 여러 구현 방식을 사용하는 것은 매우 일반적입니다.


문자열 a가 문자열 b와 동일한 코드 단위 시퀀스로 구성되어 있으면, 같습니다, 즉 동일합니다.

달리 명시되지 않는 한, 모든 문자열 비교에는 같음을 사용합니다.

이러한 유형의 문자열 비교는 이전에 HTML에서 "대소문자 구분" 비교라고 불렸습니다. 서로 동일한 것으로 비교되는 문자열은 대소문자 차이(예: 대문자와 소문자)뿐만 아니라 정규화 형식이나 결합 문자 순서와 같은 다른 코드 포인트 인코딩 선택에도 민감합니다. Unicode에 따라 시각적으로 또는 정규적으로 동등한 두 문자열도 여전히 서로 동일하지 않을 수 있습니다. [HTML] [UNICODE]

문자열 potentialPrefix는 다음 단계가 true를 반환하는 경우 문자열 input의 코드 단위 접두사입니다:

  1. i를 0으로 둡니다.

  2. true인 동안:

    1. i가 potentialPrefix의 길이보다 크거나 같으면 true를 반환합니다.

    2. i가 input의 길이보다 크거나 같으면 false를 반환합니다.

    3. potentialPrefixCodeUnit를 potentialPrefix의 i번째 코드 단위로 둡니다.

    4. inputCodeUnit를 input의 i번째 코드 단위로 둡니다.

    5. potentialPrefixCodeUnit가 inputCodeUnit가 아니면 false를 반환합니다.

    6. i를 i + 1로 설정합니다.

예를 들어 문자열 중 하나가 U+0020 SPACE부터 U+007E (~)까지의 범위에 있는 문자만 포함하는 리터럴이어서 코드 단위를 다루고 있음이 문맥상 명확한 경우, "input이 potentialPrefix로 시작합니다"는 "potentialPrefix가 input의 코드 단위 접두사입니다"와 같은 의미로 사용할 수 있습니다.

알 수 없는 값에는 명시적으로 표현하는 것이 좋습니다: targetString은 userInput의 코드 단위 접두사입니다. 하지만 리터럴에는 더 간단한 표현을 사용할 수 있습니다: userInput은 다음으로 시작합니다 "!".

문자열 potentialSuffix는 다음 단계가 true를 반환하는 경우 문자열 input의 코드 단위 접미사입니다:

  1. i를 1로 둡니다.

  2. true인 동안:

    1. potentialSuffixIndex를 potentialSuffix의 길이 − i로 둡니다.

    2. inputIndex를 input의 길이 − i로 둡니다.

    3. potentialSuffixIndex가 0보다 작으면 true를 반환합니다.

    4. inputIndex가 0보다 작으면 false를 반환합니다.

    5. potentialSuffixCodeUnit를 potentialSuffix의 potentialSuffixIndex번째 코드 단위로 둡니다.

    6. inputCodeUnit를 input의 inputIndex번째 코드 단위로 둡니다.

    7. potentialSuffixCodeUnit가 inputCodeUnit가 아니면 false를 반환합니다.

    8. i를 i + 1로 설정합니다.

예를 들어 문자열 중 하나가 U+0020 SPACE부터 U+007E (~)까지의 범위에 있는 문자만 포함하는 리터럴이어서 코드 단위를 다루고 있음이 문맥상 명확한 경우, "input이 potentialSuffix로 끝납니다"는 "potentialSuffix가 input의 코드 단위 접미사입니다"와 같은 의미로 사용할 수 있습니다.

알 수 없는 값에는 명시적으로 표현하는 것이 좋습니다: targetString은 domain의 코드 단위 접미사입니다. 하지만 리터럴에는 더 간단한 표현을 사용할 수 있습니다: domain은 다음으로 끝납니다 ".".


문자열 a는 다음 단계가 true를 반환하는 경우 문자열 b보다 코드 단위 기준으로 작습니다:

  1. b가 a의 코드 단위 접두사이면 false를 반환합니다.

  2. a가 b의 코드 단위 접두사이면 true를 반환합니다.

  3. a의 n번째 코드 단위가 b의 n번째 코드 단위와 다른 가장 작은 인덱스를 n으로 둡니다. (어느 문자열도 다른 문자열의 접두사가 아니므로 그러한 인덱스가 반드시 존재합니다.)

  4. a의 n번째 코드 단위가 b의 n번째 코드 단위보다 작으면 true를 반환합니다.

  5. false를 반환합니다.

이는 JavaScript의 < 연산자 및 문자열 배열에 대한 sort() 메서드가 사용하는 정렬 순서와 일치합니다. 이 순서는 각 문자열의 16비트 코드 단위를 비교하여 매우 효율적이고 일관되며 결정적인 정렬 순서를 생성합니다. 결과 순서는 특정 알파벳 순서나 사전식 순서와 일치하지 않으며, 특히 서로게이트 쌍으로 표현되는 코드 포인트의 경우 그렇습니다. [ECMA-262]

예를 들어 코드 포인트 U+FF5E FULLWIDTH TILDE (~)는 분명히 코드 포인트 U+1F600 (😀)보다 작지만, 물결표는 단일 코드 단위 0xFF5E로 구성되고 스마일리는 두 코드 단위 0xD83D와 0XDE00으로 구성되므로, 스마일리가 물결표보다 코드 단위 기준으로 작습니다.


문자열 string 내에서 start부터 길이 length인 코드 단위 부분 문자열은 다음과 같이 결정됩니다:

  1. 단언: start와 length는 음수가 아닙니다.

  2. 단언: start + length는 string의 길이보다 작거나 같습니다.

  3. result를 빈 문자열로 둡니다.

  4. 범위 start부터 start + length까지(끝 제외)의 각 i에 대해: string의 i번째 코드 단위를 result에 추가합니다.

  5. result를 반환합니다.

문자열 string 내에서 start부터 end까지의 코드 단위 부분 문자열은 string 내에서 start부터 길이 end − start인 코드 단위 부분 문자열입니다.

문자열 string의 start부터 끝까지의 코드 단위 부분 문자열은 string 내에서 start부터 string의 길이까지의 코드 단위 부분 문자열입니다.

"Hello world" 내에서 1부터 길이 3인 코드 단위 부분 문자열은 "ell"입니다. 이는 1부터 4까지의 코드 단위 부분 문자열로도 표현할 수 있습니다.

이 알고리즘에 주어지는 숫자는 코드 단위 자체의 인덱스가 아니라 코드 단위 사이의 위치로 생각하는 것이 가장 좋습니다. 반환되는 부분 문자열은 이러한 위치 사이의 코드 단위로 구성됩니다. 이것이 예를 들어 빈 문자열 내에서 0부터 0까지의 코드 단위 부분 문자열이 빈 문자열인 이유를 설명합니다. 빈 문자열에는 인덱스 0에 코드 단위가 존재하지 않더라도 그렇습니다.

문자열 string 내에서 start부터 길이 length인 코드 포인트 부분 문자열은 다음과 같이 결정됩니다:

  1. 단언: start와 length는 음수가 아닙니다.

  2. 단언: start + length는 string의 코드 포인트 길이보다 작거나 같습니다.

  3. result를 빈 문자열로 둡니다.

  4. 범위 start부터 start + length까지(끝 제외)의 각 i에 대해: string의 i번째 코드 포인트를 result에 추가합니다.

  5. result를 반환합니다.

문자열 string 내에서 start부터 end까지의 코드 포인트 부분 문자열은 string 내에서 start부터 길이 end − start인 코드 포인트 부분 문자열입니다.

문자열 string의 start부터 끝까지의 코드 포인트 부분 문자열은 string 내에서 start부터 string의 코드 포인트 길이까지의 코드 포인트 부분 문자열입니다.

일반적으로 개발자가 제공한 위치나 길이를 사용하는 경우에는 코드 단위 부분 문자열을 사용합니다. JavaScript에서 문자열 인덱싱이 그러한 방식으로 동작하기 때문입니다. 예를 들어 CharacterData 클래스의 메서드를 참조하십시오. [DOM]

그렇지 않은 경우에는 코드 포인트 부분 문자열이 더 적합할 가능성이 높습니다. 예를 들어 "👽" 내에서 0부터 길이 1인 코드 포인트 부분 문자열은 "👽"인 반면, "👽" 내에서 0부터 길이 1인 코드 단위 부분 문자열은 단일 서로게이트 U+D83B를 포함하는 문자열입니다.


동형 문자열 input을 동형 인코딩하려면: 바이트 시퀀스를 반환합니다. 이 바이트 시퀀스의 길이는 input의 코드 포인트 길이와 같고, 그 바이트의 값은 input의 코드 포인트의 값과 동일한 순서로 같습니다.


문자열을 ASCII 소문자화하려면, 문자열의 모든 ASCII 대문자 알파벳을 ASCII 소문자 알파벳의 해당 코드 포인트로 바꿉니다.

문자열을 ASCII 대문자화하려면, 문자열의 모든 ASCII 소문자 알파벳을 ASCII 대문자 알파벳의 해당 코드 포인트로 바꿉니다.

문자열 A는 A를 ASCII 소문자화한 결과가 B를 ASCII 소문자화한 결과와 같은 경우 문자열 B에 대한 ASCII 대소문자를 구분하지 않는 일치입니다.

ASCII 문자열 input을 ASCII 인코딩하려면: input의 동형 인코딩을 반환합니다.

동형 인코딩과 UTF-8 인코딩은 input에 대해 동일한 바이트 시퀀스를 반환합니다.

바이트 시퀀스 input을 ASCII 디코딩하려면 다음 단계를 실행합니다:

  1. 단언: input의 모든 바이트는 ASCII 바이트입니다.

    참고: 이 전제 조건은 이 입력에 대해 동형 디코딩과 UTF-8 디코딩이 동일한 문자열을 반환하도록 보장합니다.

  2. input의 동형 디코딩을 반환합니다.


문자열에서 줄바꿈을 제거하려면, 문자열에서 모든 U+000A LF 및 U+000D CR 코드 포인트를 제거합니다.

문자열에서 줄바꿈을 정규화하려면, 모든 U+000D CR U+000A LF 코드 포인트 쌍을 하나의 U+000A LF 코드 포인트로 바꾼 다음, 남아 있는 모든 U+000D CR 코드 포인트를 U+000A LF 코드 포인트로 바꿉니다.

문자열에서 선행 및 후행 ASCII 공백을 제거하려면, 문자열의 시작이나 끝에 있는 모든 ASCII 공백을 제거합니다.

문자열에서 ASCII 공백을 제거하고 축약하려면, 문자열에서 ASCII 공백인 하나 이상의 연속된 코드 포인트 시퀀스를 하나의 U+0020 SPACE 코드 포인트로 바꾼 다음, 해당 문자열에서 모든 선행 및 후행 ASCII 공백을 제거합니다.


문자열 input에서 조건 condition을 충족하는 코드 포인트 시퀀스를 수집하려면, 호출 알고리즘에서 input 내의 위치를 추적하는 위치 변수 position이 주어졌을 때:

  1. result를 빈 문자열로 둡니다.

  2. position이 input의 끝을 지나지 않고, input 내 position에 있는 코드 포인트가 조건 condition을 충족하는 동안:

    1. 해당 코드 포인트를 result의 끝에 추가합니다.

    2. position을 1만큼 전진시킵니다.

  3. result를 반환합니다.

이 알고리즘은 수집된 코드 포인트를 반환하는 것 외에도 호출 알고리즘의 위치 변수를 갱신합니다.

문자열 input 내에서 ASCII 공백을 건너뛰려면, 위치 변수 position이 주어졌을 때, position이 주어진 input에서 ASCII 공백인 코드 포인트 시퀀스를 수집합니다. 수집된 코드 포인트는 사용하지 않지만 position은 계속 갱신됩니다.


특정 구분자 코드 포인트 delimiter를 기준으로 문자열 input을 엄격하게 분할하려면:

  1. position을 input에 대한 위치 변수로 두고, 처음에는 input의 시작을 가리키도록 합니다.

  2. tokens를 처음에는 비어 있는 문자열의 목록으로 둡니다.

  3. token을 position이 주어진 input에서 delimiter와 같지 않은 코드 포인트 시퀀스를 수집한 결과로 둡니다.

  4. token을 tokens에 추가합니다.

  5. position이 input의 끝을 지나지 않는 동안:

    1. 단언: input 내 position에 있는 코드 포인트는 delimiter입니다.

    2. position을 1만큼 전진시킵니다.

    3. token을 position이 주어진 input에서 delimiter와 같지 않은 코드 포인트 시퀀스를 수집한 결과로 둡니다.

    4. token을 tokens에 추가합니다.

  6. tokens를 반환합니다.

이 알고리즘은 아래의 일반적으로 사용되는 ASCII 공백 기준 및 쉼표 기준 변형과 달리 "엄격한" 분할입니다. 이 두 변형은 중간에 섞여 있는 ASCII 공백을 처리하는 여러 방식에서 더 관대합니다.

문자열 input을 ASCII 공백을 기준으로 분할하려면:

  1. position을 input에 대한 위치 변수로 두고, 처음에는 input의 시작을 가리키도록 합니다.

  2. tokens를 처음에는 비어 있는 문자열의 목록으로 둡니다.

  3. position이 주어진 input 내에서 ASCII 공백을 건너뜁니다.

  4. position이 input의 끝을 지나지 않는 동안:

    1. token을 position이 주어진 input에서 ASCII 공백이 아닌 코드 포인트 시퀀스를 수집한 결과로 둡니다.

    2. token을 tokens에 추가합니다.

    3. position이 주어진 input 내에서 ASCII 공백을 건너뜁니다.

  5. tokens를 반환합니다.

문자열 input을 쉼표를 기준으로 분할하려면:

  1. position을 input에 대한 위치 변수로 두고, 처음에는 input의 시작을 가리키도록 합니다.

  2. tokens를 처음에는 비어 있는 문자열의 목록으로 둡니다.

  3. position이 input의 끝을 지나지 않는 동안:

    1. token을 position이 주어진 input에서 U+002C (,)가 아닌 코드 포인트 시퀀스를 수집한 결과로 둡니다.

      token은 빈 문자열일 수 있습니다.

    2. token에서 선행 및 후행 ASCII 공백을 제거합니다.
    3. token을 tokens에 추가합니다.

    4. position이 input의 끝을 지나지 않았다면:

      1. 단언: input 내 position에 있는 코드 포인트는 U+002C (,)입니다.

      2. position을 1만큼 전진시킵니다.

  4. tokens를 반환합니다.

선택적인 구분자 문자열 separator를 사용하여 문자열의 목록 list를 연결하려면 다음 단계를 실행합니다:

  1. list가 비어 있으면 빈 문자열을 반환합니다.

  2. separator가 주어지지 않았다면 separator를 빈 문자열로 설정합니다.

  3. list의 항목들을 순서대로 separator로 서로 구분하여 내용으로 가지는 문자열을 반환합니다.

집합 set을 직렬화하려면 U+0020 SPACE를 사용한 set의 연결을 반환합니다.

4.8. 시간

시간은 moment 및 duration 명세 타입을 사용하여 표현합니다. JavaScript와 이 값을 교환하거나 생성할 때에는 High Resolution Time § 3 명세 작성자를 위한 도구의 권고를 따르세요. [HR-TIME]

4.9. 싱글턴

다음 타입들은 알고리즘의 이해를 돕기 위해 입력 또는 출력으로 사용할 수 있습니다. 이들은 주어진 알고리즘의 흐름에 미치는 영향 이외에는 관찰 가능한 표현이 없으며, "is"로만 비교할 수 있습니다.

allowed

어떤 연산이 허용됨을 나타내며, 종종 blocked와 반대되는 의미로 사용됩니다.

blocked

어떤 연산이 허용되지 않음을 나타내며, 종종 allowed와 반대되는 의미로 사용됩니다.

failure

어떤 연산이 예상대로 진행되지 않았음을 나타내며, 종종 success와 반대되거나 더 구체적인 타입과 함께 사용됩니다.

success

어떤 연산이 예상대로 진행되었음을 나타내며, 종종 failure와 반대되는 의미로 사용됩니다.

다음 알고리즘은 success 또는 failure를 반환합니다:

  1. 예상하지 못한 문제가 발생했다면 failure를 반환한다.

  2. success를 반환한다.

이 알고리즘을 호출하는 쪽에서는 결과를 다음과 같이 평가할 수 있습니다:

  1. result가 failure라면 모든 처리를 정상적으로 종료하고 중단한다.

  2. Assert: result가 success임을 확인한다.

  3. …

Failure는 실패할 수 있거나 값을 반환할 수 있는 알고리즘의 결과로 자주 사용됩니다:

  1. status가 200보다 작거나 599보다 크면 failure를 반환한다.

  2. status를 반환한다.

5. 데이터 구조

관례적으로, 명세들은 의미에 대한 공통된 이해를 바탕으로 다양한 모호한 명세 수준의 데이터 구조를 사용해 왔습니다. 이는 대체로 잘 작동하지만, 반복 순서나 이미 포함하는 ordered set에 item을 append할 때 등 경계 사례에서 모호함이 발생할 수 있습니다. 또한, map과 같은 더 복잡한 데이터 구조에서 다양한 표기법과 표현이 파생되기도 했습니다.

이 표준은 공통 기반을 마련하기 위해, 몇 가지 일반적인 데이터 구조와 그것을 다루기 위한 표기법 및 표현을 제공합니다.

5.1. 리스트

목록은 유한한 순서의 항목으로 구성되는 명세 타입입니다.

표기상의 편의를 위해 목록을 표현하는 데 리터럴 구문을 사용할 수 있으며, 목록을 U+00AB («) 및 U+00BB (»)로 둘러싸고, 그 항목을 U+002C (,)로 구분합니다. 대괄호 안에 목록의 0부터 시작하는 인덱스를 지정하여 인덱싱 구문을 사용할 수 있습니다. 존재합니다와 함께 사용하는 경우를 제외하면 인덱스는 범위를 벗어날 수 없습니다.

example을 목록 « "a", "b", "c", "a" »로 둡니다. 그러면 example[1]은 문자열 "b"입니다.

표기상의 편의를 위해 여러 변수를 목록의 항목에 할당하는 다중 할당 구문을 사용할 수 있으며, 할당할 변수를 U+00AB («) 및 U+00BB (»)로 둘러싸고(목록과 동일), 각 변수 이름을 U+002C (,)로 구분합니다. 목록의 크기는 할당할 변수의 수와 같아야 합니다. 그런 다음 주어진 각 변수는 목록의 해당 인덱스에 있는 항목의 값으로 설정됩니다.

  1. value를 목록 « "a", "b", "c" »로 둡니다.

  2. « a, b, c »를 value로 둡니다.

  3. 단언: a는 "a"입니다.

  4. 단언: b는 "b"입니다.

  5. 단언: c는 "c"입니다.

사용자 입력에서 얻은 목록의 경우처럼 목록의 내용을 완전히 제어할 수 없는 경우에는, 목록 다중 할당 구문을 사용하기 전에 목록의 크기를 확인하여 예상한 크기인지 보장해야 합니다.

  1. list의 크기가 3이 아니면 실패를 반환합니다.

  2. « a, b, c »를 list로 둡니다.

목록 a와 b가 주어졌을 때 동등성은 a의 목록 크기가 b의 크기와 같고 a[i]가 a의 각 인덱스 i에 대해 b[i]와 같으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.


순서 있는 집합이 아닌 목록에 추가한다는 것은 주어진 항목을 목록의 끝에 추가하는 것입니다.

순서 있는 집합이 아닌 목록 A를 목록 B로 확장하려면, B의 각 item에 대해 item을 A에 추가합니다.

  1. ghostbusters를 « "Erin Gilbert", "Abby Yates" »로 둡니다.

  2. ghostbusters를 « "Jillian Holtzmann", "Patty Tolan" »로 확장합니다.

  3. 단언: ghostbusters의 크기는 4입니다.

  4. 단언: ghostbusters[2]는 "Jillian Holtzmann"입니다.

순서 있는 집합이 아닌 목록에 앞에 추가한다는 것은 주어진 항목을 목록의 시작 부분에 추가하는 것입니다.

순서 있는 집합이 아닌 목록에서 대체한다는 것은 주어진 조건과 일치하는 목록의 모든 항목을 주어진 항목으로 대체하거나, 일치하는 항목이 없으면 아무 작업도 하지 않는 것입니다.

위 정의는 목록이 순서 있는 집합인 경우 수정됩니다. 아래의 순서 있는 집합 추가, 앞에 추가 및 대체를 참조하십시오.

항목을 인덱스 앞의 목록에 삽입한다는 것은 주어진 항목을 목록에서 주어진 인덱스 − 1과 주어진 인덱스 사이에 추가하는 것입니다. 주어진 인덱스가 0이면 주어진 항목을 목록의 앞에 추가합니다.

목록에서 0개 이상의 항목을 제거하려면:

  1. sizeBefore를 list의 크기로 둡니다.

  2. 주어진 조건과 일치하는 모든 항목을 목록에서 제거하거나, 일치하는 항목이 없으면 아무 작업도 하지 않습니다.

  3. list의 크기가 sizeBefore보다 작으면 true를 반환하고, 그렇지 않으면 false를 반환합니다.

목록 « x, y, z, x »에서 x를 제거한다는 것은 목록에서 x와 같은 모든 항목을 제거하는 것입니다. 이제 목록은 « y, z »와 동등합니다.

목록 « "a", "b", "ab", "ba" »에서 문자열 "a"로 시작하는 모든 항목을 제거한다는 것은 항목 "a"와 "ab"를 제거하는 것입니다. 이제 목록은 « "b", "ba" »와 동등합니다.

목록을 비운다는 것은 그 목록의 모든 항목을 제거하는 것입니다.

목록은 목록의 항목 중 하나가 해당 항목과 같으면 그 항목을 포함합니다. 또한 목록 list와 인덱스 index에 대해 "list[index]가 존재합니다"라고 나타낼 수도 있습니다.

목록의 크기는 목록이 포함하는 항목의 수입니다.

목록은 그 크기가 0이면 비어 있습니다.

목록의 인덱스를 가져오려면, 0부터 목록의 크기까지(끝 제외)의 범위를 반환합니다.

목록을 반복하면서 각 항목에 대해 순서대로 일련의 단계를 수행하려면, "각 item에 대해(list의)" 형식의 표현을 사용하고, 그다음 이어지는 문장에서 item에 대해 작업합니다.

목록 list을 슬라이스하려면, 선택적 정수 from(기본값 0)과 선택적 정수 to(기본값은 list의 크기)를 사용하여 다음 단계를 수행합니다. 이 단계들은 list와 동일한 지정의 목록을 반환합니다.

  1. 단언: from은 0보다 크거나 같습니다.

  2. 단언: to는 list의 크기보다 작거나 같습니다.

  3. 단언: to는 from보다 크거나 같습니다.

  4. slice를 list와 동일한 지정의 새 목록으로 둡니다.

  5. from부터 to까지(끝 제외)의 범위의 각 i에 대해: list[i]를 slice에 추가합니다.

  6. slice를 반환합니다.

목록 list에 중복 항목이 있는지 확인하려면:

  1. seenItems를 « »로 둡니다.

  2. list의 각 item에 대해:

    1. seenItems가 item을 포함하면 true를 반환합니다.

    2. item을 seenItems에 추가합니다.

  3. false를 반환합니다.

목록 list를 복제한다는 것은 list의 슬라이스를 반환하는 것입니다.

항목 자체는 어떤 방식으로도 복제되지 않으므로 이는 "얕은 복제"입니다.

original을 순서 있는 집합 « "a", "b", "c" »로 둡니다. original을 복제하면 새 순서 있는 집합 clone이 생성되므로, clone에서 "a"를 "foo"로 대체하면 « "foo", "b", "c" »가 되지만, original[0]은 여전히 문자열 "a"입니다.

목록 list를 역순으로 뒤집는다는 것은 동일한 지정의 새 목록 reversed를 만들고, list의 각 item에 대해 item을 reversed의 앞에 추가하는 것입니다.

목록 list를 작은 값 비교 알고리즘 lessThanAlgo를 사용하여 오름차순으로 정렬한다는 것은 새 목록 sorted를 만드는 것입니다. 이 목록은 list와 동일한 항목을 포함하지만, lessThanAlgo에 따라 각 항목이 뒤따르는 항목(있는 경우)보다 작도록 정렬됩니다. 동일하게 정렬되는 항목 (즉, 두 비교 모두에서 lessThanAlgo가 false를 반환하는 항목)의 경우 sorted에서의 상대적 순서는 list에서와 같아야 합니다.

목록 list를 작은 값 비교 알고리즘 lessThanAlgo를 사용하여 내림차순으로 정렬한다는 것은 새 목록 sorted를 만드는 것입니다. 이 목록은 list와 동일한 항목을 포함하지만, lessThanAlgo에 따라 각 항목이 앞선 항목(있는 경우)보다 작도록 정렬됩니다. 동일하게 정렬되는 항목 (즉, 두 비교 모두에서 lessThanAlgo가 false를 반환하는 항목)의 경우 sorted에서의 상대적 순서는 list에서와 같아야 합니다.

original을 목록 « (200, "OK"), (404, "Not Found"), (null, "OK") »로 둡니다. a의 두 번째 항목이 b의 두 번째 항목보다 코드 단위 기준으로 작을 때 a가 b보다 작다고 하여 original을 오름차순으로 정렬하면 결과는 « (404, "Not Found"), (200, "OK"), (null, "OK") »입니다.


목록 타입은 JavaScript 명세에서 유래했습니다(그곳에서는 대문자로 시작하는 List라고 합니다). 쉽게 참조할 수 있도록 그 정의의 일부 요소를 여기에 반복해서 제시하고, 목록을 조작하기 위한 확장된 용어를 제공합니다. JavaScript에서 List가 요구되는 경우에는 언제나 여기에 정의된 목록을 사용할 수 있으며, 둘은 동일한 타입입니다. [ECMA-262]

5.1.1. 스택

일부 목록은 스택으로 지정됩니다. 스택은 목록이지만, 관례적으로 이를 조작할 때는 추가, 앞에 추가 또는 제거 대신 다음 연산을 사용합니다.

스택에 푸시한다는 것은 해당 스택에 추가하는 것입니다.

스택에서 팝하려면: 스택이 비어 있지 않으면, 마지막 항목을 제거하고 이를 반환합니다. 그렇지 않으면 아무것도 반환하지 않습니다.

스택을 피크하려면: 스택이 비어 있지 않으면, 마지막 항목을 반환합니다. 그렇지 않으면 아무것도 반환하지 않습니다.

스택은 목록이지만, 여기에 각 항목에 대해를 사용해서는 안 됩니다. 대신 동안과 팝의 조합을 사용하는 것이 더 적절합니다.

5.1.2. 큐

일부 목록은 큐로 지정됩니다. 큐는 목록이지만, 관례적으로 이를 조작할 때는 추가, 앞에 추가 또는 제거 대신 다음 연산을 사용합니다.

큐에 인큐한다는 것은 해당 큐에 추가하는 것입니다.

큐에서 디큐한다는 것은 큐가 비어 있지 않으면 첫 번째 항목을 제거하고 반환하며, 비어 있으면 아무것도 반환하지 않는 것입니다.

큐는 목록이지만, 여기에 각 항목에 대해를 사용해서는 안 됩니다. 대신 동안과 디큐의 조합을 사용하는 것이 더 적절합니다.

5.1.3. 셋

일부 목록은 순서 있는 집합으로 지정됩니다. 순서 있는 집합은 목록이지만, 서로 같은 두 항목을 포함해서는 안 된다는 추가적인 의미론을 갖습니다.

웹 플랫폼의 거의 모든 경우에는 순서 없는 집합 대신 순서 있는 집합이 필요합니다. 상호 운용성을 위해 개발자에게 노출되는 집합 내용의 열거가 브라우저 간에 일관되어야 하기 때문입니다. 순서가 중요하지 않은 경우에도 여전히 순서 있는 집합을 사용합니다. 구현체는 순서를 관찰할 수 없다는 사실을 바탕으로 최적화할 수 있습니다.

목록 input이 주어졌을 때 집합을 생성하려면:

  1. result를 빈 집합으로 둡니다.

  2. input의 각 item에 대해, item을 result에 추가합니다.

  3. result를 반환합니다.

순서 있는 집합에 추가하려면: 집합이 주어진 항목을 포함하면 아무 작업도 하지 않습니다. 그렇지 않으면 일반적인 목록 추가 연산을 수행합니다.

순서 있는 집합 A를 목록 B로 확장하려면, B의 각 item에 대해 item을 A에 추가합니다.

순서 있는 집합의 앞에 추가하려면: 집합이 주어진 항목을 포함하면 아무 작업도 하지 않습니다. 그렇지 않으면 일반적인 목록 앞에 추가 연산을 수행합니다.

순서 있는 집합 set 내에서 item과 replacement가 주어졌을 때 대체하려면: set이 item 또는 replacement를 포함하면, 둘 중 처음 나타나는 것을 replacement로 대체하고 나머지 모든 인스턴스를 제거합니다.

순서 있는 집합 « "a", "b", "c" »에서 "a"를 "c"로 대체하면 « "c", "b" »가 됩니다. « "c", "b", "a" »에서도 « "c", "b" »가 됩니다.

순서 있는 집합 set은 set의 각 item에 대해 superset이 item을 포함하면, 다른 순서 있는 집합 superset의 부분집합입니다 (반대로 superset은 set의 상위 집합입니다).

이는 순서 있는 집합이 자기 자신의 부분집합이면서 상위 집합이기도 함을 의미합니다.

집합 A는 A가 B의 부분집합이고 B의 상위 집합이면, 집합 B와 순서와 무관하게 동등합니다.

순서 있는 집합 « 1, 2 »와 « 2, 1 »은 순서와 무관하게 동등하지만, 목록의 동등성은 그 항목의 순서를 고려하므로 두 집합은 같지 않습니다.

순서 있는 집합 A와 B의 교집합은 새 순서 있는 집합 set을 생성하고, A의 각 item에 대해 B가 item을 포함하면, item을 set에 추가한 결과입니다.

순서 있는 집합 A와 B의 합집합은 A를 set으로 복제하고, B의 각 item에 대해 item을 set에 추가한 결과입니다.

순서 있는 집합 A와 B의 차집합은 새 순서 있는 집합 set을 생성하고, A의 각 item에 대해 B가 item을 포함하지 않으면, item을 set에 추가한 결과입니다.


m이 n보다 크거나 같은 경우, n부터 m까지(양 끝 포함)의 범위는 n부터 m까지의 모든 정수를 연속적으로 증가하는 순서로 포함하는 새 순서 있는 집합을 생성합니다.

m이 n보다 큰 경우, n부터 m까지(끝 제외)의 범위는 n부터 m − 1까지의 모든 정수를 연속적으로 증가하는 순서로 포함하는 새 순서 있는 집합을 생성합니다. m이 n과 같으면 빈 순서 있는 집합을 생성합니다.

1부터 4까지(양 끝 포함)의 범위의 각 n에 대해, …

5.2. 맵

순서 있는 맵, 또는 때로는 단순히 "맵"이라고도 하는 것은 유한한 순서의 튜플로 구성되는 명세 타입이며, 각 튜플은 키와 값으로 구성되고, 어떤 두 키도 서로 같지 않습니다. 이러한 각 튜플을 항목이라고 합니다.

순서 있는 집합과 마찬가지로, 기본적으로 구현체 간의 상호 운용성을 위해 맵은 순서가 있어야 한다고 가정합니다.

순서 있는 맵을 표현하는 데 리터럴 구문을 사용할 수 있습니다. 순서 있는 맵은 U+00AB («)와 U+005B ([)로 시작하고 U+005D (])와 U+00BB (»)로 끝내며, 각 항목의 key와 value는 U+2192 (→)로 구분하고, 항목들은 U+002C (,)로 구분합니다.

example을 순서 있는 맵 «[ "a" → `x`, "b" → `y` ]»로 둡니다. 그러면 example["a"]는 바이트 시퀀스 `x`입니다.

순서 있는 맵 a와 b가 주어졌을 때 동등성은 두 순서 있는 맵에 대해 다음 조건을 만족하면 true를 반환합니다. a의 크기가 b의 크기와 같고, a의 각 항목에 있는 키와 값이 같은 위치에 있는 b의 항목의 키와 같고 그 값도 항목의 값과 같아야 합니다. 그렇지 않으면 false를 반환합니다.


순서 있는 맵 map에서 키 key와 선택적인 default가 주어졌을 때 항목의 값을 가져오려면:

  1. map이 key를 포함하지 않고 default가 주어졌다면 default를 반환합니다.

  2. 단언: map은 key를 포함합니다.

  3. map에서 키가 key와 같은 항목의 값을 반환합니다.

맵 바로 뒤의 대괄호 안에 키를 지정하는 인덱싱 구문을 사용하여 항목의 값을 가져오는 것을 나타낼 수도 있습니다. 맵 바로 뒤에 지정합니다. 기본값은 기본값으로라는 구문 뒤에 기본값을 추가하여 지정할 수 있습니다.

map["test"]가 존재하면, map["test"]를 반환합니다.

example을 순서 있는 맵 «[ "a" → "x", "b" → "y" ]»로 둡니다. 그러면 example["a"]는 example["a"]에 기본값으로 "z"를 지정한 것과 같으며, 즉 "x"입니다. example["c"]는 단언에 걸립니다. example["c"]에 기본값으로 "z"를 지정하면 "z"입니다.

순서 있는 맵의 항목을 주어진 값으로 설정하려면, 맵에 주어진 키를 가진 항목이 있으면 기존 항목의 값을 갱신하고, 그러한 항목이 없으면 주어진 키/값을 가진 새 항목을 맵의 끝에 추가합니다. 또한 순서 있는 맵 map, 키 key, 값 value에 대해 "map[key]를 value로 설정합니다"라고 나타낼 수도 있습니다.

순서 있는 맵에서 항목을 제거한다는 것은 주어진 조건과 일치하는 맵의 모든 항목을 제거하거나, 일치하는 항목이 없으면 아무 작업도 하지 않는 것입니다. 조건이 특정 키를 가지는 것이라면, 순서 있는 맵 map과 키 key에 대해 "map[key]를 제거합니다"라고 나타낼 수도 있습니다.

순서 있는 맵을 비운다는 것은 맵에서 모든 항목을 제거하는 것입니다.

순서 있는 맵은 주어진 키와 같은 키를 가진 항목이 존재하면 해당 키를 가진 항목을 포함합니다. 또한 해당 키가 주어진 키와 같아야 합니다. 이를 순서 있는 맵 map과 키 key에 대해 "map[key]가 존재합니다"라고 나타낼 수도 있습니다.

순서 있는 맵의 키를 가져오려면, 맵의 항목에 있는 각 키를 항목으로 가지는 새 순서 있는 집합을 반환합니다.

순서 있는 맵의 값을 가져오려면, 맵의 항목에 있는 각 값을 항목으로 가지는 새 목록을 반환합니다.

순서 있는 맵의 크기는 맵에서 키를 가져오기를 실행한 결과의 크기입니다.

순서 있는 맵은 그 크기가 0이면 비어 있습니다.

순서 있는 맵을 반복하면서 각 항목에 대해 순서대로 일련의 단계를 수행하려면, "map의 각 key → value에 대해" 형식의 표현을 사용하고, 이어지는 문장에서 key와 value를 대상으로 작업합니다.

순서 있는 맵 map을 복제한다는 것은 새 순서 있는 맵 clone을 생성하고, map의 각 key → value에 대해, clone[key]를 value로 설정하는 것입니다.

키와 값 자체는 어떤 방식으로도 복제되지 않으므로 이는 "얕은 복제"입니다.

original을 순서 있는 맵 «[ "a" → «1, 2, 3», "b" → «» ]»로 둡니다. original을 복제하면 새 순서 있는 맵 clone이 생성되므로, clone["a"]를 «-1, -2, -3»으로 설정하면 «[ "a" → «-1, -2, -3», "b" → «» ]»가 되고 original은 변경되지 않습니다. 그러나 clone["b"]에 4를 추가하면 clone과 original 모두에서 해당 값이 수정됩니다. 둘 다 동일한 목록을 가리키기 때문입니다.

맵 map을 작은 값 비교 알고리즘 lessThanAlgo를 사용하여 오름차순으로 정렬한다는 것은 새 맵 sorted를 만드는 것입니다. 이 맵은 map과 동일한 항목을 포함하지만, lessThanAlgo에 따라 각 항목이 뒤따르는 항목(있는 경우)보다 작도록 정렬됩니다. 동일하게 정렬되는 항목 (즉, 두 비교 모두에서 lessThanAlgo가 false를 반환하는 항목)의 상대적 순서는 sorted에서 map에서와 같아야 합니다.

맵 map을 작은 값 비교 알고리즘 lessThanAlgo를 사용하여 내림차순으로 정렬한다는 것은 새 맵 sorted를 만드는 것입니다. 이 맵은 map과 동일한 항목을 포함하지만, lessThanAlgo에 따라 각 항목이 앞선 항목(있는 경우)보다 작도록 정렬됩니다. 동일하게 정렬되는 항목 (즉, 두 비교 모두에서 lessThanAlgo가 false를 반환하는 항목)의 상대적 순서는 sorted에서 map에서와 같아야 합니다.

5.3. 구조체

구조체는 유한한 집합의 항목으로 구성된 명세 타입이며, 각 항목에는 고유하고 변경할 수 없는 이름이 있습니다. 항목은 정의된 타입의 값을 보유합니다.

이메일은 로컬 부분(문자열)과 호스트(호스트)로 구성된 구조체의 예입니다.

의미 없는 알고리즘은 이 정의를 다음과 같이 사용할 수 있습니다:

  1. email을 로컬 부분이 "hostmaster"이고 호스트가 infra.example인 이메일로 둡니다.
  2. …

정의에서 달리 지정하지 않는 한, 튜플이 아닌 구조체는 자기 자신과만 같습니다. 즉 두 구조체가 서로 동일하면 그 동등성은 true를 반환하고, 그렇지 않으면 false를 반환합니다.

구조체 a와 b가 주어졌을 때 항목별 동등성은 a의 각 항목이 동일한 이름을 가진 b의 항목과 같으면 true를 반환하고, 그렇지 않으면 false를 반환합니다. 구조체의 정의에서는 그 동등성이 항목별 동등성이라고 지정할 수 있습니다.

위의 이메일 정의를 사용하면:

  1. email을 로컬 부분이 "hostmaster"이고 호스트가 infra.example인 이메일로 둡니다.

  2. sameEmail을 email로 둡니다.

  3. otherEmail을 로컬 부분이 "hostmaster"이고 호스트가 infra.example인 이메일로 둡니다.

  4. 단언: email은 sameEmail과 같습니다. 이는 서로 동일하기 때문입니다.

  5. 단언: email은 otherEmail과 같지 않습니다. 서로 동일하지 않기 때문입니다.

대신 이메일의 정의에서 이메일의 동등성이 항목별 동등성이라고 지정했다면, email은 otherEmail과 같게 됩니다. 이는 두 로컬 부분이 서로 동일하고 두 호스트가 같기 때문입니다.

따라서 정의에서 동등성을 지정하지 않은 구조체를 순서 있는 맵의 키나 순서 있는 집합의 항목으로 사용하면, 바로 그 동일한 구조체를 사용해야만 다시 찾을 수 있습니다. 이를 원하지 않는다면, 해당 정의에서 동등성을, 예를 들어 항목별 동등성으로 지정해야 합니다.

5.3.1. 튜플

튜플은 구조체이며, 그 항목에는 순서가 있습니다. 표기상의 편의를 위해 튜플을 표현하는 데 리터럴 구문을 사용할 수 있으며, 튜플을 괄호로 둘러싸고 그 항목을 U+002C (,)로 구분합니다. 이 표기법을 사용하려면 이름이 문맥상 명확해야 합니다. 이는 첫 번째 인스턴스 앞에 튜플에 지정된 이름을 붙여서 할 수 있습니다. 대괄호 안에 튜플의 0부터 시작하는 인덱스를 지정하여 인덱싱 구문을 사용할 수 있습니다. 인덱스는 범위를 벗어날 수 없습니다.

상태는 코드( 숫자)와 텍스트(바이트 시퀀스)로 구성된 튜플의 예입니다.

사용법을 보여주기 위해 상태 튜플을 조작하는 의미 없는 알고리즘은 다음과 같습니다:

  1. statusInstance를 상태 (200, `OK`)로 둡니다.
  2. statusInstance를 (301, `FOO BAR`)로 설정합니다.
  3. statusInstance의 코드가 404이면, …

마지막 단계는 "statusInstance[0]이 404이면, …"라고 쓸 수도 있습니다. 이는 튜플의 이름에 명시적인 정의가 없는 경우 더 적절할 수 있습니다.

모든 구조체가 튜플인 것은 의도된 것입니다. Infra Standard를 사용하는 문서는 종속성이 사용하는 리터럴 구문을 깨뜨리지 않고 구조체에 새 이름을 추가할 수 있는 유연성이 필요할 수 있습니다. 그런 경우에는 튜플이 적절하지 않습니다.

튜플의 동등성은 정의에서 달리 지정하지 않는 한 항목별 동등성입니다.

튜플을 튜플이 아닌 구조체로 변경하면 그 정의에서 이를 지정하지 않는 한 더 이상 항목별 동등성을 가지지 않는다는 의미이기도 합니다.

6. JSON

이 절의 알고리즘에서 사용하는 규칙은 JavaScript 명세의 규칙을 따릅니다. [ECMA-262]

문자열 string이 주어졌을 때 JSON 문자열을 JavaScript 값으로 구문 분석하려면:

  1. ? Call(%JSON.parse%, undefined, « string »)을 반환합니다.

바이트 시퀀스 bytes가 주어졌을 때 JSON 바이트를 JavaScript 값으로 구문 분석하려면:

  1. string을 bytes에 UTF-8 디코딩을 실행한 결과로 둡니다. [ENCODING]

  2. string이 주어졌을 때 JSON 문자열을 JavaScript 값으로 구문 분석한 결과를 반환합니다.

JavaScript 값 value가 주어졌을 때 JavaScript 값을 JSON 문자열로 직렬화하려면:

  1. result를 ? Call(%JSON.stringify%, undefined, « value »)로 둡니다.

    %JSON.stringify%에 추가 인수가 전달되지 않으므로, 결과 문자열에는 공백이 삽입되지 않습니다.

  2. result가 undefined이면 TypeError를 던집니다.

    이는 value에 JSON 표현이 없는 경우, 예를 들어 undefined이거나 함수인 경우 발생할 수 있습니다.

  3. 단언: result는 문자열입니다.

  4. result를 반환합니다.

JavaScript 값 value가 주어졌을 때 JavaScript 값을 JSON 바이트로 직렬화하려면:

  1. string을 value가 주어졌을 때 JavaScript 값을 JSON 문자열로 직렬화한 결과로 둡니다.

  2. string에 UTF-8 인코딩을 실행한 결과를 반환합니다. [ENCODING]


위 연산은 JavaScript 값을 직접 대상으로 수행됩니다. 특히 이는 관련 객체나 배열이 특정 JavaScript 렐름에 연결되어 있음을 의미합니다. 표준에서는 JSON과 렐름에 독립적인 맵, 목록, 문자열, 불리언, 숫자 및 null 사이를 변환하는 것이 더 편리한 경우가 많습니다.

문자열 string이 주어졌을 때 JSON 문자열을 Infra 값으로 구문 분석하려면:

  1. jsValue를 ? Call(%JSON.parse%, undefined, « string »)로 둡니다.

  2. jsValue가 주어졌을 때 JSON에서 파생된 JavaScript 값을 Infra 값으로 변환한 결과를 반환합니다.

바이트 시퀀스 bytes가 주어졌을 때 JSON 바이트를 Infra 값으로 구문 분석하려면:

  1. string을 bytes에 UTF-8 디코딩을 실행한 결과로 둡니다. [ENCODING]

  2. string이 주어졌을 때 JSON 문자열을 Infra 값으로 구문 분석한 결과를 반환합니다.

JavaScript 값 jsValue가 주어졌을 때 JSON에서 파생된 JavaScript 값을 Infra 값으로 변환하려면:

  1. jsValue가 null이거나, jsValue가 Boolean이거나, jsValue가 String이거나, 또는 jsValue가 Number이면, jsValue를 반환합니다.

  2. IsArray(jsValue)가 true이면:

    1. result를 빈 목록으로 둡니다.

    2. length를 ! ToLength(! Get(jsValue, "length"))로 둡니다.

    3. 0부터 length − 1까지(양 끝 포함)의 범위의 각 index에 대해:

      1. indexName을 ! ToString(index)으로 둡니다.

      2. jsValueAtIndex를 ! Get(jsValue, indexName)으로 둡니다.

      3. infraValueAtIndex를 jsValueAtIndex가 주어졌을 때 JSON에서 파생된 JavaScript 값을 Infra 값으로 변환한 결과로 둡니다.

      4. infraValueAtIndex를 result에 추가합니다.

    4. result를 반환합니다.

  3. result를 빈 순서 있는 맵으로 둡니다.

  4. ! jsValue.[[OwnPropertyKeys]]()의 각 key에 대해:

    1. jsValueAtKey를 ! Get(jsValue, key)로 둡니다.

    2. infraValueAtKey를 jsValueAtKey가 주어졌을 때 JSON에서 파생된 JavaScript 값을 Infra 값으로 변환한 결과로 둡니다.

    3. result[key]를 infraValueAtKey로 설정합니다.

  5. result를 반환합니다.

문자열, 불리언, 숫자, null, 목록 또는 문자열을 키로 사용하는 맵 value가 주어졌을 때 Infra 값을 JSON 문자열로 직렬화하려면:

  1. jsValue를 value가 주어졌을 때 Infra 값을 JSON 호환 JavaScript 값으로 변환한 결과로 둡니다.

  2. ! Call(%JSON.stringify%, undefined, « jsValue »)을 반환합니다.

    %JSON.stringify%에 추가 인수가 전달되지 않으므로, 결과 문자열에는 공백이 삽입되지 않습니다.

문자열, 불리언, 숫자, null, 목록 또는 문자열을 키로 사용하는 맵 value가 주어졌을 때 Infra 값을 JSON 바이트로 직렬화하려면:

  1. string을 value가 주어졌을 때 Infra 값을 JSON 문자열로 직렬화한 결과로 둡니다.

  2. string에 UTF-8 인코딩을 실행한 결과를 반환합니다. [ENCODING]

value가 주어졌을 때 Infra 값을 JSON 호환 JavaScript 값으로 변환하려면:

  1. value가 문자열, 불리언, 숫자 또는 null이면 value를 반환합니다.

  2. value가 목록이면:

    1. jsValue를 ! ArrayCreate(0)으로 둡니다.

    2. i를 0으로 둡니다.

    3. value의 각 listItem에 대해:

      1. listItemJSValue를 listItem이 주어졌을 때 Infra 값을 JSON 호환 JavaScript 값으로 변환한 결과로 둡니다.

      2. ! CreateDataPropertyOrThrow(jsValue, ! ToString(i), listItemJSValue)을 수행합니다.

      3. i를 i + 1로 설정합니다.

    4. jsValue를 반환합니다.

  3. 단언: value는 맵입니다.

  4. jsValue를 ! OrdinaryObjectCreate(null)로 둡니다.

  5. value의 각 mapKey → mapValue에 대해:

    1. 단언: mapKey는 문자열입니다.

    2. mapValueJSValue를 mapValue가 주어졌을 때 Infra 값을 JSON 호환 JavaScript 값으로 변환한 결과로 둡니다.

    3. ! CreateDataPropertyOrThrow(jsValue, mapKey, mapValueJSValue)을 수행합니다.

  6. jsValue를 반환합니다.

명세에서 JavaScript 값을 직접 조작하는 것은 거의 적절하지 않으므로, 이 알고리즘을 사용하는 대신 Infra 값을 JSON 문자열로 직렬화하거나 Infra 값을 JSON 바이트로 직렬화하는 것을 권장합니다. Infra 값을 JSON 호환 JavaScript 값으로 변환해야 한다고 판단하신다면, 사용 사례를 논의할 수 있도록 이슈를 제출해 주세요.

7. 관대한 base64

forgiving-base64 인코딩은 byte sequence data가 주어졌을 때, RFC 4648의 section 4에 정의된 base64 알고리즘을 data에 적용하여 결과를 반환한다. [RFC4648]

이 명칭은 forgiving-base64 encode와 forgiving-base64 decode 간의 대칭성을 위해 붙여졌으며, forgiving-base64 decode는 RFC와 달리 특정 입력에 대한 오류 처리를 정의한다는 점에서 다르다.

forgiving-base64 디코딩은 string data가 주어졌을 때 다음 절차를 따른다:

  1. data에서 모든 ASCII 공백을 제거한다.

  2. data의 코드 포인트 길이를 4로 나눈 나머지가 0일 경우:

    1. data가 하나 또는 두 개의 U+003D(=) 코드 포인트로 끝나면, 이들을 data에서 제거한다.

  3. data의 코드 포인트 길이를 4로 나눈 나머지가 1이면, 실패를 반환한다.

  4. data에 아래 중 하나가 아닌 코드 포인트가 있으면

    실패를 반환한다.

  5. output을 빈 byte sequence로 둔다.

  6. buffer를 비트 추가가 가능한 빈 버퍼로 둔다.

  7. position을 위치 변수로 data의 시작을 가리키게 둔다.

  8. position이 data의 끝을 지나지 않을 때 반복:

    1. position이 가리키는 코드 포인트를 RFC 4648의 Table 1: The Base 64 Alphabet의 두 번째 열에서 찾는다. 같은 행의 첫 번째 셀에 있는 수를 n으로 둔다. [RFC4648]

    2. n에 해당하는 6비트를(가장 앞 비트부터) buffer에 추가한다.

    3. buffer에 24비트가 쌓이면, 이를 세 개의 8비트 big-endian 숫자로 해석한다. 이 숫자와 같은 값을 갖는 세 바이트를 output에 같은 순서로 추가하고, buffer를 비운다.

    4. position을 1만큼 앞으로 옮긴다.

  9. buffer가 비어 있지 않다면, 12 또는 18비트가 들어있다. 12비트라면 마지막 4비트를 버리고 남은 8비트를 8비트 big-endian 숫자로 해석한다. 18비트라면 마지막 2비트를 버리고 남은 16비트를 두 개의 8비트 big-endian 숫자로 해석한다. 이 숫자(들)에 해당하는 바이트 1~2개를 output에 같은 순서로 추가한다.

    버려진 비트 때문에, 예를 들어 "YQ"와 "YR" 모두 `a`를 반환하게 된다.

  10. output을 반환한다.

8. 네임스페이스

HTML 네임스페이스는 "http://www.w3.org/1999/xhtml"이다.

MathML 네임스페이스는 "http://www.w3.org/1998/Math/MathML"이다.

SVG 네임스페이스는 "http://www.w3.org/2000/svg"이다.

XLink 네임스페이스는 "http://www.w3.org/1999/xlink"이다.

XML 네임스페이스는 "http://www.w3.org/XML/1998/namespace"이다.

XMLNS 네임스페이스는 "http://www.w3.org/2000/xmlns/"이다.

감사의 글

진심으로 감사드립니다: Addison Phillips, Andreu Botella, Aryeh Gregor, Ben Kelly, Chris Rebert, Daniel Ehrenberg, Dominic Farolino, Gabriel Pivovarov, Ian Hickson, Jakob Ackermann, Jake Archibald, Jeff Hodges, Jeffrey Yasskin, Jungkee Song, Leonid Vasilyev, Maciej Stachowiak, Malika Aubakirova, Martin Thomson, Michael™ Smith, Mike West, Mike Taylor, Ms2ger, Noam Rosenthal, Pavel "Al Arz" Kurochkin, Philip Jägenstedt, Rashaun "Snuggs" Stovall, Sergey Shekyan, Simon Pieters, Tab Atkins, Tobie Langel, triple-underscore, Wolf Lammen, 그리고 Xue Fuqiao 여러분 모두 멋진 분들입니다!

이 표준은 Anne van Kesteren (Apple, annevk@annevk.nl)와 Domenic Denicola (Google, d@domenic.me)가 작성했습니다.

지적 재산권

Copyright © WHATWG (Apple, Google, Mozilla, Microsoft). 이 저작물은 크리에이티브 커먼즈 저작자표시 4.0 국제 라이선스에 따라 라이선스가 부여됩니다. 이 중 일부가 소스 코드에 포함되는 경우, 해당 부분은 BSD 3-Clause License로 라이선스됩니다.

이 문서는 현행 표준입니다. 특허 검토 버전이 필요하신 분은 현행 표준 검토초안을 참고해 주세요.

색인

이 명세서에서 정의된 용어

참조에 의해 정의된 용어

참조

규범적 참조

[ECMA-262]
ECMAScript 언어 명세. URL: https://tc39.es/ecma262/multipage/
[ENCODING]
Anne van Kesteren. 인코딩 표준. 현행 표준. URL: https://encoding.spec.whatwg.org/
[HR-TIME]
Yoav Weiss. 고해상도 시간. URL: https://w3c.github.io/hr-time/
[Infra]
Anne van Kesteren; Domenic Denicola. 인프라 표준. 현행 표준. URL: https://infra.spec.whatwg.org/
[RFC20]
V.G. Cerf. 네트워크 교환을 위한 ASCII 형식. 1969년 10월. 인터넷 표준. URL: https://www.rfc-editor.org/info/rfc20/
[RFC2119]
S. Bradner. 요구사항 수준을 나타내기 위해 RFC에서 사용하는 핵심 단어. 1997년 3월. 현행 모범 사례. URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC4648]
S. Josefsson. Base16, Base32 및 Base64 데이터 인코딩. 2006년 10월. 제안 표준. URL: https://www.rfc-editor.org/info/rfc4648/
[UNICODE]
유니코드 표준. URL: https://www.unicode.org/versions/latest/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준. 현행 표준. URL: https://webidl.spec.whatwg.org/

비규범적 참조

[COOKIES]
A. Barth. HTTP 상태 관리 메커니즘. 2011년 4월. 제안 표준. URL: https://httpwg.org/specs/rfc6265.html
[DOM]
Anne van Kesteren. DOM 표준. 현행 표준. URL: https://dom.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch 표준. 현행 표준. URL: https://fetch.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML 표준. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[RFC6797]
J. Hodges; C. Jackson; A. Barth. HTTP 엄격한 전송 보안(HSTS). 2012년 11월. 제안 표준. URL: https://www.rfc-editor.org/info/rfc6797/
[RFC791]
J. Postel. 인터넷 프로토콜. 1981년 9월. 인터넷 표준. URL: https://www.rfc-editor.org/info/rfc791/
[RFC8174]
B. Leiba. RFC 2119 핵심 단어에서 대문자와 소문자의 모호성. 2017년 5월. 현행 모범 사례. URL: https://www.rfc-editor.org/info/rfc8174/
[RFC8259]
T. Bray, Ed.. JavaScript 객체 표기법(JSON) 데이터 교환 형식. 2017년 12월. 인터넷 표준. URL: https://www.rfc-editor.org/info/rfc8259/
[STORAGE]
Anne van Kesteren. 스토리지 표준. 현행 표준. URL: https://storage.spec.whatwg.org/
[URL]
Anne van Kesteren. URL 표준. 현행 표준. URL: https://url.spec.whatwg.org/
[XML]
Tim Bray; et al. 확장 가능한 마크업 언어(XML) 1.0(제5 판). 2008년 11월 26일. REC. URL: https://www.w3.org/TR/xml/