ECMA2023 살펴보기

도도묵·2023년 5월 24일
  웹을 지원하는 브라우저가 다양해지면서 Apple, Microsoft, Mozilla, Google 등의 웹 관련 주요 단체들은 브라우저 간의 호환성을 유지하기 위해 표준화를 진행하였고, 이에 대한 기술 규격이 ECMA 인터네셔널(European Computer Manufactureers Association International)에 제출되어 채택되었다. 채택된 해당 기술 규격은 ECMA-262의 이름으로 ECMAScript language Specification(ECMAScript 언어 표준)가 되어 TC39 위원회에 의해 관리되고 있다. TC39는 주로 자바스크립트를 표준화하는 작업을 진행 중에 있으며 매년마다 새로운 버전의 ECMAScript를 출판하고 있다.
  올 해도 어김없이 새로운 버전 ECMA2023이 출시되었다. 이 글은 ECMA2023에서 javascript의 어떤 변경점이 생겼는지 알아보고자 작성되었다.


채택된 내용은 총 4가지다.

  1. Array find from last

  2. Hashbang Grammar

  3. Symbols as WeakMap keys

  4. Change Array by Copy

구체적으로 어떤 부분이 바뀌었는지 알아보자.




📌 ECMA2023

⭐️ 1. Array find from last

제목부터 알 수 있듯이 배열의 값을 뒤로부터 찾을 수 있는 기능이다.
기존 javascript에서는 indexOf, lastIndexOf로 배열의 특정 인덱스 값을 찾거나 find, findIndex 같은 기능을 통해 배열에서 조건을 만족하는 요소 또는 인덱스를 찾는 기능이 존재했다.
하지만 해당 함수들은 배열의 마지막에서 첫 번째까지 요소를 찾는 방법은 제공하지 않았기 때문에 reverse 함수를 이용해 arr.reverse().find()가 이 역할을 대체하곤 했다. 그러나 이 방법에는 3가지 문제점이 존재한다.

  • 불필요한 변이(mutation)

  • 불필요한 복사(copy)

  • 복잡한 인덱스 계산


설명하자면
const arr = [1,2,3]
const arr2 = arr.reverse()

console.log('arr : ', arr)
console.log('arr2 : ', arr2)
console.log('arr과 arr2은 같다? : ', arr === arr2)
number타입의 arr 배열을 reverse로 역전시키고 arr2에 담았다. 그럼 arr2에는 [3,2,1]이 담길 것이다. 그렇다면 arr은 어떠한가? arr과 arr2은 다른 구조를 갖고 있어야하지 않는가?
놀랍게도 답은
arr : [3,2,1]
arr2 : [3,2,1]
arr과 arr2은 같다? : true
가 나온다.
reverse()함수는 기존 배열값에 변이(mutation)을 일으키기 때문에 arr 역시 [3,2,1]로 변하는 것이다. 또한 arr2에는 arr의 주소 값이 담기기 때문에 const arr2로 새로운 변수를 초기화했다 해도 값은 주소를 가르키고 있기 때문에 arr과 arr2가 같다고 나오는 것이다. 때문에 다른 주소를 가진 배열을 선언하고 싶다면
const arr2 = [...arr].reverse()
와 같은 불필요한 복사(copy) 과정을 한번 더 거치게 되는 귀찮은 상황이 발생하게 되는 것이다.
또한
[...arr].reverse().findIndex()
findIndex 호출 후 다시 인덱스를 계산하고, -1 처리하는 인덱스에 대한 복잡한 계산이 요구되었다.
이러한 문제점을 해결하기 위해 직관적인, 효과적인 무언가가 필요했고 findLast와 findLastIndex가 출시되었다.


⭐️ 1. findLast, findLastIndex

기존 Array.prototype.find, Array.prototype.findIndex와 같은 기능이지만 끝에서부터 시작으로 검색될 것이다.
const arr =  [1,2,3,4]

/* ===기존=== */
// find
[...arr].reverse().find(e => e % 2 === 1) // 3

// findIndex
arr.length -1 - [...arr].reverse().findIndex(e => e % 2 === 1) // 2 (값이 없으면 -1이 나와야 되는데 4가 된다)


/* ===ECMA2023=== */
// find
arr.findLast(e => e % 2 === 1) // 3

// findIndex
arr.findLastIndex(e => e % 2 === 1) // 2 (값이 없으면 -1)
reverse로 원본 배열이 변이되는 일도, 불필요한 복사나 복잡한 인덱스 처리도 더이상 필요하지 않다.


⭐️ 2. Hashbang Grammar

Javascript 파일이 CLI에서 실행되는 경우 Javascript 엔진이 해당 파일을 실행하기 전 HashBang(#!) 기호가 달려 있을 경우, 해당 라인을 무시할 수 있다 ex). ==#!/usr/bin/env== . 단 소스코드의 첫 줄에서만 유효하게 적용된다(실제 CLI 환경에서 사용되지 않기 때문에 다른 줄에서는 의도한 용도로 사용될 수 없다고 함, 다른 줄 주석 처리를 원할 경우 // 사용).


⭐️ 3. Symbols as WeakMap keys

기존 객체만 들어갈 수 있었던 WeakMap 키에 ECMA2023이 적용되면서 Symbol 또한 적용이 가능해졌다.

Symbol: 고유 키를 부여해 다른 코드와 충돌하지 않는 내장 객체. Symbol('key')은 주어진 값에 대한 심볼을 반환하지만, 호출마다 새로운 심볼을 생성합니다. (Symbol('foo') !== Symbol('foo'))

다만 고유함과 다시 생성할 수 없다는 점 때문에 등록되지 않은 심볼만 사용이 가능하다.


⭐️ 4. Change Array by Copy

Javascript에서 제공하는 Array.prototype의 함수들 중 특정 함수는 함수 사용시 기존 배열이 변경되는 경우도 있고, 얕은 복사를 통한 새로운 배열 객체를 제공해주는 함수도 존재한다. 해당 함수가 어떻게 값을 리턴하는지는 함수에 대한 설명을 읽어보거나 직접 사용해봐야만 알 수 있기 때문에 Javascript 개발자들은 이 함수들이 어떤 기능을 하는지 외우는 경우가 대부분이다. 밑에 예시를 한번 보자.
// splice
let arr = [1,2,3,4] 
let arr2 = arr.splice() 
// arr: [2,3,4] 
// arr2: [1]

// slice
let arr = [1,2,3,4] 
let arr2 = arr.slice(0,1)
// arr: [1,2,3,4]
// arr2: [1]
둘 다 동일한 값을 제공하지만, 원본 배열의 변경 여부에는 차이가 있다. 이처럼 기능은 비슷할수 있지만 어떤 형태의 배열을 사용하는지 혼돈을 줄 수 있다. 이런 부분들을 해소하기 위해 ECMA2023에서는 기존의 배열을 해치지 않는 새로운 함수들이 제공된다.

🌟 toReversed

기존 배열의 순서를 역전해 새로운 배열을 만들어 전달한다.
const arr = [1, 2, 3]
arr.toReversed() // => [3, 2, 1]
arr // => [1, 2, 3]

🌟 toSorted( compare function )

비교 함수를 넣어 새로운 배열을 반환한다(default: 오름차순).
const arr = [3, 1, 2]
arr.toSorted() // => [1, 2, 3]
arr // [3, 1, 2]

🌟 toSpliced( start, delectCnt, ...item )

배열의 요소 삭제 또는 교체
const arr = [1,2,3]
arr.toSpliced(0,1) // => [2, 3]
arr // [1,2,3]

🌟 with( index, value )

배열의 인덱스 요소 value 교체
const arr = [1,1,3]
arr.with(1,2) // => [1,2,3]
arr // => [1,1,3]
profile
나만의 성장 일기

1개의 댓글

comment-user-thumbnail
2023년 8월 25일

좋은 글 감사합니다.

답글 달기