ES6 이후의 이야기 (1)

ChangHyeon Bae·2023년 1월 12일
0

JavaScript

목록 보기
5/8
post-thumbnail

ES6 이후로 프론트엔드는 다양한 변화를 겪어왔다고 한다. 하지만 도대체 어떤 변화가 있었기에 그런말이 나오는지에 대해 한번 알아보자 !

⭐️ ES2016

💡 Array.prototype.includes()

  • includes() 메서드는 배열이 특정 요소를 포함하고 있는지 판별한다.
  • 반환값은 boolean
const array1 = [1, 2, 3];

console.log(array1.includes(2)); // expected output: true 

const pets = ['cat', 'dog', 'bat'];

console.log(pets.includes('cat'); // true
console.log(pets.includes('at'); // false

💡 지수 연산자 Math.pow()

console.log(Math.pow(7, 3)); // 7 * 7 * 7 = 343
// 7**3 = 343
console.log(Math.pow(2, 3)); // 2 * 2 * 2 = 8
// 2**3 = 8

⭐️ ES2017

  • ES2017에는 우리가 잘 알고 있는 async/await 등 많은 기능이 추가 되었다. 그래서 이를 제외하고 나머지 어떤 기능이 나왔는지에 대해 알아보자

💡 문자열 패딩

String.prototye.padStart(), String.prototype.padEnd()

  • padStart() 메서드는 현재 문자열의 시작을 다른 문자열로 채워, 주어진 길이를 만족하는 새로운 문자열을 반환한다. 채워 넣기는 대상 문자열의 시작(좌측) 부터 적용 된다.
  • 반환값은 string
const str1 = '5';

console.log(str1.padStart(2, '0') // "05"
            
const fullNumber ='203499002125581' // length : 16
const last4Digits = fullNumber.slice(-4); // 5581
const padStartNumber = last4Digits.padStart(fullNumber.length, '*'); // fullNumber.length : 16 
const padEndNumber = last4Digits.padEnd(fullNumber.length, '*'); 

console.log(padStartNumber); // "************5581" 나머지 부분 왼쪽부터 '*'로 채운다.
console.log(padEndNumber); // "5581************" padEnd() 메서드는 오른쪽 부터 채워진다. 

💡 Object.entries() 와 Object.values()

  • object.entries() 메서드는 for...in와 같은 순서로 주어진 객체 자체의 enumerable 속성
    [key, value] 쌍의 배열을 반환 한다.
  • for...in 루프가 다른점은 프로토 타입의 체인의 속성도 열거한다는 점이다.
  • 반환값은 Array
const object = {
  a: 'somestring'
  b: 42
};
console.log(Object.entries(object)); // [['a', 'somestring'],['b', 42]]

for(const [key, value] of Object.entries(object)) {
  console.log(`${key} : ${value}`);  
  // "a : somestring "
  // "b : 42 "
  

💡 Object.getOwnProperyDescriptors()

  • Object.getOwnProperyDescriptors() 메서드는 주어진 객체 자신의 속성(즉, 객체에 직접 제공하는 속성, 객체의 프로토 타입 체인을 따라 존재하은 덕택에 제공하는게 아닌? )에 대한 속성 설명자(description)을 반환한다.
  • 반환값은 객체에 존재하는 경우 주어진 속성의 설명자 없으면 undefined
let o, d;
o = { get foo() { return 17; } };
d = Object.getOwnPropertyDescriptor(o, 'foo');
// d는 { configurable: true, enumerable: true, get: /*getter 함수 */, set: undefined }

o = { bar: 42 }
d = Object.getOwnPropertyDescriptor(o, 'bar');
// d는 { configurable: true, enumerable: true, value: 42, writable: true }                                   

💡 Trailing Comma (=final commas)

  • 새로운 엘리먼트나 매개변수, 속성을 JavaScript 코드에 추가
  • 새로운 속성 추가시, 마지막 중에 trailing comma 가 있을 시, 그 줄을 수정 없이 그대로 복사해서 쓸 수 있다
  • 버전 관리 이력이 간단하고 코드 편집이 더 편해진다.
  • JavaScript 초기(배열 리터럴), ECMA5(객체 리터럴), ECMA2017(함수의 매개변수) 허용
  • JSON에서는 허용을 하지 않는다.
// 배열
let arr = [1, 2, 3, , ,];
arr.length; // 5 

// forEact(), map()을 이용해 배열 순회시에는 빈 슬롯을 무시
arr.forEach((e) => console.log(e)) // 1, 2, 3

// 객체
let object = {
  foo: "bar",
  baz: "qwerty",
  age: 42,
};

// 함수
function f(p) { }
function f(p, ) { }

(p) => { };
(p, ) => { };

💡 Atomics, SharedArrayBuffer

  • 멀티 스레드 환경을 지원하기 위한 기능들이다. 간략하게 짚고 넘어가보자.
  • Atomics
    • Atomics 객체는 atomic 작업을 정적 메서드로 제공한다.
    • SharedArrayBufferArrayBuffer 객체와 함께 사용
    • 메모리가 공유되면 여러 스레드가 메모리에서 동일한 데이터를 읽고 쓸 수 있다.
    • Atomic 연산은 예측 가능한 값을 쓰고 읽고, 다음 연산이 시작되기 전에 연산을 완료하여 중단 되지 않도록 한다.
  • ShredArrayBuffer
    • 제네릭, 고정된 길이의 원시 바이너리 데이터 버퍼를 표현하는데 사용된다.
    • ArrayBuffer 객체와 유사하지만, 공유된 메모리상의 뷰를 생성하는데 사용될 수 있다.
    • ArrayBuffer와 달리, SharedArrayBuffer는 분리 될 수 없다.
    • 반환값은 크기가 지정된 새로운 SharedArrayBuffer 객체이다. 컨텐츠는 '0'으로 초기화 된다.

⭐️ ES2018

💡 Object rest/spread

  • ES6(2009년)에서 배열 의 spread, rest가 가능해졌고, ES2018에서는 객체에도 사용하는 것이 가능해졌다.
const Object = {
  a: 1,
  b: 3,
  c: 'cc',
  d: 100
};

const {a, b, ...z} = Object;
console.log(a); // 1
console.log(b); // 3
console.log(z); // { c: 'cc', d: 100 }

const spread = {
  ...Object,
  a: 10,
  e: 30,
};

console.log(spread); // { a: 10, b: 3, c: 'cc', d: 100, e: 30}

💡 Aysnc iteration

  • 제너레이터 함수와 for of 문에서 async를 사용할 수 있다.
(async() => {
  const promises = [1, 2, 3].map((timer) => (
    new Promise((resolve) => {
      setTimeout(() => resolve(timer), timer*1000);
    })
  ));

  for await (const result of promises) {
    console.log(result); // 1 2 3
  }
})();

💡 Promise.prototype().finally

  • Promise가 처리되면 충족되거나 거부되는지 여부에 관계없이 지정된 콜백 함수가 실행된다.
  • Promise가 성공적으로 수행 되었는지, 거절되었는지에 관계없이 Primise가 처리 된후 코드가 무조건 한번은 실행되는것을 제공한다.
  • 반환값은 Promise 객체
let isLoading = true;
fetch(myRequest).then((response) => {
  var contentType = response.headers.get("content-type");
  if(contentType && contentType.includes("application/json")) {
    return response.json()
  }
  throw new TypeError("Ooops!!!!, we haven't got JSON");
})
.then((json) => {/* process ypur JSON further */})
.catch((error) => { console.log(error} )
.finally(() => { isLoading = false });

💡 정규식 추가

  • s(dotAll) 플래그 : '.' 표현식은 개행문자를 제외한 모든 문자였으나, s플래그를 달면 개행식도 포함하게 된다.
const test = /foo.bar/s.test("foo\nbar"); // true
console.log(test); // true
  • 명명된 캡쳐 그룹 -> (?) 구문을 사용하여 캡쳐 그룹에 원하는 이름을 붙일 수 있다.
let regex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
let result = regex.exec("2021-06-21");
console.log(result); // ['2021-06-21', '2021', '06, '21', { day: ... }]
console.log(result.groups); // {day : '21', month: '06', year: '2021'}
  • 룩비하인드 어서션

    • 룩비하인드 어서션을 사용하면 패턴 앞에 다른 패턴이 있는지 여부를 확인할 수 있다고 한다.
    • 긍정 룩비하인드 어서션
    const regex = /(?<=\$)\d+(\.\d*)?/;
    const result = regex.exec('$10.53');
    [
    "10.53",
    ".53"
    ]
    const result2 = regex.exec('&10.53');
    // null
    • 부정 룩비하인드 어서션 (?<!…)
  • 유니코드 속성 이스케이프 \p{...}(긍정), \P{...}(부정) 형식으로 유니코드 속성 이스케이프를 사용할 수 있다.

    const sentence = 'A ticket to 大阪 costs ¥2000 👌.';
    const regexpEmojiPresentation = /\p{Emoji_Presentation}/gu;
    console.log(sentence.match(regexpEmojiPresentation));
    // Expected output: Array ["👌"]
    const regexpNonLatin = /\P{Script_Extensions=Latin}+/gu;
    console.log(sentence.match(regexpNonLatin));
    // Expected output: Array [" ", " ", " 大阪 ", " ¥2000 👌."]
    const regexpCurrencyOrPunctuation = /\p{Sc}|\p{P}/gu;
    console.log(sentence.match(regexpCurrencyOrPunctuation));
    // Expected output: Array ["¥", "."]
    

⭐️ ES2019

💡 Array.prototype.flat()

  • float() 메서드는 모든 하위 배열 요소를 지정한 깊이까지 재귀적으로 이어붙인 새로운 배열을 생성한다
  • 반환값은 하위 배열을 이어붙인 새로운 배열
const newArr = arr.flat([depth])
  
const arr1 = [1, 2, [3, 4]];
arr1.flat(); // [1, 2, 3, 4]
  
const arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat(); // [1, 2, 3, 4, [5, 6]]
  
const arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2); // [1, 2, 3, 4, 5, 6]
  
const arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity); // [ 1, 2, 3, 4, 5, 6, ... ]

💡 Array.prototype.flatMap()

  • flatMap() 메서드는 먼저 매핑 함수를 사용해 각 엘리먼트에 대해 map 수행 후, 결과를 새로운 배열로 평탄화 하는 작업을 한다.
  • 깊이 1의 flat이 뒤따르는 map과 동일하다.
  • flatMap으 아주 유용하며 둘을 하나의 메소드로 병합할 때 조금 더 효율적이다.
  • 반환값은 각 엘리먼트가 callback 함수의 결과이고, 깊이 1로 평탄화된 새로운 배열
let arr1 = [1, 2, 3, 4];

arr1.map(x => [x * 2]); // [[2], [4], [6], [8]]
  
arr1.flatMap(x => [x * 2] // [2, 4, 6, 8]
  
// 한 레벨만 평탄화
arr1.flatMap(x => [[x * 2]]); // [[2], [4], [6], [8]]
  
let arr2 = ["it's Sunny in", "", "California"]
  
arr2.map(x => x.split("")); // [["it's", "Sunny", "in"], [""], ["Califonia"]]
  
arr2.flatMap(x => x.split("")); // ["it's", "Sunny", "in", "Califonia"]
  

💡 Object.fromEntries()

  • Object.fromEntries() 메서드는 키값 쌍의 목록을 객체로 바꾼다.
const entries = new Map([['foo', 'bar'], [baz', 42]]);
  
const obj = Object.fromEntries(entries);
  
console.log(obj) // { foo: 'bar', baz: 42 }

💡 String.prototype.trimStart()

  • trimStart() 메서드는 문자열 시작 부분의 공백을 제거한다.
  • trimLeft()라는 별칭을 가지고 있다.
const greeting = '    Hello World!   ';

console.log(greeting); //'    Hello World!   '

console.log(greeting.trimStart()); // 'Hello World!   '

💡 String.prototype.trimEnd()

  • trimEnd() 메서드는 trimStart()메서드와 반대로 오른쪽 공백을 제거한다.
  • trimRight()라는 별칭을 가지고 있다.
const greeting = '    Hello World!   ';

console.log(greeting); //'    Hello World!   '

console.log(greeting.trimEnd()); // '    Hello World!'

💡 선택적 catch 할당

  • ES2019 이전에는 catch절에 항상 예외 변수를 포함해야 하지만, ES2019에서는 이를 생략할 수 있다.
try {
  ...
} catch {
  ...
  }

💡 Function.prototype.toString()

  • toString()은 문자열을 반환하는 Object의 대표적인 방법이다.
function Dog(name) {
  this.name = name
}

const dog1 = new Dog("Barrey");

Dog.prototype.toString = function dogToString() {
  return `{this.name}`
};
  
console.log(dog1.toString()); // Barrey

💡 Symbol.prototype.description

  • 심벌 객체의 description은 해당 심벌 객체의 설명을 반환한다.
  
console.log(Symbol('desc').toString());   // "Symbol(desc)"  
  
console.log(Symbol('desc').description); // "desc"

console.log(Symbol.iterator.description); // "Symbol.iterator"

console.log(Symbol.for('foo').description); // "foo"

console.log(`${Symbol('foo').description}bar`); // "foobar"

⭐️ 2016 ~ 2019 1부 마무리

  • 코딩을 하면서 봤던 메서드들도 있고, 실제로 사용해보지는 않았지만 보거나, 들어본 개념들도 몇개 있었고, 이런게 있었나 싶은 메서드도 많이 추가된거 같다. 예를 들어 Atomics/ SharedArrayBuffer 멀티 스레드 환경에서 사용하는 메서드 인데 이와 관련해서 사용한적이 없어 개념 정리를 하면서 이해가 잘 안갔던 부분이다. 그리고 MDN 문서의 예시를 같이 보면서하니 글로 읽는것보다 더 이해를 잘 할 수 있었다.
  • 이번 게시물 같은 경우는 양이 너무 많아서 1부, 2부로 나누었고 1부에서는 2016 ~ 2019를 정리하였고 2부에서는 2020 ~ 2021를 정리할 예정이다. 2부에서도 1부 못지않게 많은 유용한 메서드들이 나왔다. 그리고 우리가 지금 코딩을 하면서 사용하는 메서드들도 눈에 많이 띈다.

🔗 참고

정확하지 않은 정보가 있을 수 있습니다. 댓글을 통해 피드백 주시면 적극적으로 반영하겠습니다🥲

profile
모든 결과는 내가 하기 나름이다 🔥

0개의 댓글