[ ES6+ 문법 ]

Corini·2022년 4월 27일
0

JavaScriptes

목록 보기
6/13
post-thumbnail

**[ ES6+ 문법 ]**

ES6+

ES란 ECMAScript의 약자이며 자바스크립트의 표준, 스펙을 나타내는 용어다.ES6+는 2015년에 개정된 javascript 스펙 ES6를 포함한 상위 스펙을 통칭하는 말이다.

ES5 기준으로 개발을 시작했던 나로써는 ES6를 기점으로 javascript의 코드가 굉장히 간결하고 명확해졌다고 생각한다. 개발 업계는 역시 게을러지면서 발전한다..

ES6부터 추가된 기능

ES6+의 추가된 기능은 다음과 같다. 모든 기능을 전부 나열하기엔 양도 많고 범위도 정확하지 않아 내가 주로 사용하는 기능만 정리해본다. ES6에서 추가된 Promise와 classes는 다음 글에서 다루겠다.

  1. Variable (let, const)
  2. Arrow Functions (화살표 함수표현식)
  3. Template Literals (템플릿 리터럴)
  4. Shorthand property names (프로퍼티 속성 이름 생략)
  5. Destructuring Assignment (배열 및 객체 비구조화)
  6. Spread Syntax (전개 연산자)
  7. Default Parameters (기본 매개 변수)
  8. Optional Chaining (?. 문법)
  9. Array function (배열 추가 기능)

드럽게 많네..

1. Variable (let, const)

해당 내용은 내 게시글에 정리되어 있다. 한마디로 요약하자면 변수, 상수 선언 방식이 추가된 것인데 바쁘니 다음 링크를 참조하자. >> var, let, const 분석

2. Arrow Functions (화살표 함수표현식)

화살표 함수 선언식은 javascript 개발자의 편의를 위해 추가된 기능이다. 함수 표현식을 화살표 함수로 표현할 수도 있다.

기존의 함수를 선언할때는 다음과 같이 작성해야 했다.

// ES5
function fn1 (a) {
    const b = 10;
    return a + b;
}

다음은 화살표 함수 선언식이다.

// ES6
const fn1 = (a) => {
    const b = 10;
    return a + b;
}

물론 함수의 본문에 return만 있는 경우 코드를 더 줄일 수 있다. 다음과 같이 화살표 함수는 return과 {}를 생략할 수 있는데 단, 같이 생략해야한다.

// ES6
const fn1 = (a) => a;

내 생각을 말하자면 그냥 function 안쓰는게 전부인 기능이다. 일단 간지나니까 그냥 쓰자.

3. Template Literals (템플릿 리터럴)

변수와 문자열을 병합할때 + 연산자를 사용해서 문자열을 생성한 경험이 모두 있을 것 이다.ES6부터는 템플릿 리터럴 기능을 통해 변수와 문자열 병합 코드를 깔끔하게 짤 수 있다.사용법은 (back tick)으로 가능하고 ${}` 표현식으로 중간 중간 변수 삽입이 가능하다.

기존 ES5에서는 이런 형태로 문자열 병합을 했었다.

// ES5
let name = 'carrots';
let age = '18';
let hello = 'hi, my name is ' + name + '. my age is ' + age;

붙이는 변수가 늘어날 때마다 코드는 더더욱 지저분해진다. 나이스다음은 ES6에서 추가된 템플릿 리터럴 기능을 사용해보자

// ES6
let name = 'carrots';
let age = '18';
let hello = `hi, my name is ${name}. my age is ${age}`;

중간 중간 +연산자를 쓸 필요없이 수행 가능하다.

4. Shorthand property names (프로퍼티 속성 이름 생략)

object를 선언할 때 속성 이름과 변수 이름이 동일할때 생략할 수 있는 기능이다.

먼저 ES5의 코드를 보면

// ES5
const name = 'carrots';
const age = 18;

const obj = {
   name : name,
   age : age
};

다음은 ES6다. 예시와 같이 속성과 변수의 이름이 같은 경우 생략이 가능하다.속성을 추가해야되는 경우는 다음과같이 추가할 수 있다.

// ES6
const name = 'carrots';
const age = 18;

const obj = { name, age };
const obj2 = { name, age, hobby : '당근먹기' };

하나 하나 지정해야 했던 과거의 지저분한 코드가 보다 간결해졌다.

5. Destructuring Assignment (배열 및 객체 비구조화)

배열과 object 같은 데이터 객체를 꺼내서 사용할 때 조금더 편리하게 사용할 수 있다.ES5와 ES6의 데이터 사용 부분이다.

먼저 ES5로 Object에 있는 변수를 꺼내서 할당하는 코드다.

// ES5
const me = {
    name: 'carrots',
    age: 18
};

let name = me.name;
let age = me.age;

ES6의 비구조화 기능을 사용했을 때다.

// ES6
const me = {
    name: 'carrots',
    age: 18
};

let { name, age } = me;

ES5에서는 각 변수에 각 값을 할당해야 되는 반면, ES6에서는 객체의 속성을 얻기 위해 값을 중괄호 안에 넣어주면 알아서 들어간다. 이때 변수명과 object의 key는 동일해야 하며 다른 변수명으로 사용하고 싶을 땐 이렇게 구현한다.

// ES6
const me = {
    name: 'carrots',
    age: 18
};

let { name, age : myAge } = me; //age key로 꺼내 myAge라는 변수명으로 사용한다는 의미다.

배열의 경우도 동일하다. object는 {}로 묶인다. 배열은 []로 묶이기 때문에 변수 선언부의 {}를 []로만 바꿔주면 된다.

// ES6
const arr = ['apple', 'carrots', 'ggingggang', 'durian'];

let [ value1, value2, value3 ] = arr;

개인적으로 정말 편리하다.

6. Spread Syntax (전개 연산자)

기존엔 객체나 배열을 복사해서 쓸때 요소들을 전개해서 복사했어야 했다. 개발을 하다보면 정말이지 고역이다. ES6에 포함된 전개 연산자를 사용하면 한줄이면 가능하다. wow

ES5에서 객체나 배열을 복사할때 코드다.

  • 객체를 복사할 때 깊은 복사와 얕은 복사의 개념이 있다.얕은 복사를 해당 코드로 설명하자면 밑에 코드에서 copyArray를 선언할때 const copyArray = array; 이런 형태로 선언하면 array를 단순 참조하는 변수가 생성되는 것이다. array 내부의 값이 변경되면 copyArray도 변경된 값으로 출력된다. 하지만 보통 같은 데이터를 갖고 있는 다른 변수로 활용하는 목적이 대부분이다. 이럴때 깊은 복사로 새로운 객체를 선언해줘야 되는데 같은 데이터를 갖고 있는 새로운 객체를 생성하는 것이다. 깊은 복사를 ES5에서 사용하기 위해선 object.assign을 통해 새로운 객체를 만들거나 JSON.parse와 stringify를 병행하여 똥꼬쇼를 해야 새로운 객체를 만들어야 한다.
// ES5
const array = [1, 2];
const copyArray = Object.assign([], array);
copyArray[0] = 3;
console.log(array); // [1, 2]
console.log(copyArray); // [3, 2]

const object = { name : 'carrots', age : 18 };
const copyObject = JSON.parse(JSON.stringify(object));
copyObject.name = 'durian';
console.log(object); // {name : 'carrots', age : 18}
console.log(copyObject); // {name : 'durian', age : 18}

다음은 ES6의 전개 연산자를 사용했을 때다. ES6에선 기존 데이터를 전개하여 새로운 배열, 객체를 생성한다. 심플하지만 가시적으로 배열이 생성됨을 확인할 수 있다.

// ES6
const array = ['apple', 'carrots', 'ggingggang', 'durian'];
const copyArray = [ ...array ];
copyArray[0] = 3;
console.log(array); // ['apple', 'carrots', 'ggingggang', 'durian']
console.log(copyArray); // [3, 'carrots', 'ggingggang', 'durian']

const object = { name : 'carrots', age : 18 };
const copyObject = { ...object };
copyObject.name = 'durian';
console.log(object); // {name : 'carrots', age : 18}
console.log(copyObject); // {name : 'durian', age : 18}

// 여러개 합치는 것도 가능이다. 배열도 객체도 가능. 바쁘니까 예시는 배열만..
const array2 = [1, 2, 3];
const copyArray2 = [ ...array, ...copyArray ,...array2 ];
console.log(copyArray2); //['apple', 'carrots', 'ggingggang', 'durian', 'apple', 'carrots', 'ggingggang', 'durian', 1, 2, 3]
  • Rest parameter는 배열의 인수를 가져오고 새 배열을 반환하는데 사용된다. 비구조화와 전개연산자를 짬뽕하면 이런식으로도 쓸 수 있다.
// ES6
const array = ['apple', 'carrots', 'ggingggang', 'durian'];
const [ value1, value2, ...restValue ] = array; // 비구조화로 각 요소를 설정
console.log(restValue); // ['ggingggang', 'durian']

개인적으로 정말 편리하다2.

7. Default Parameters (기본 매개 변수)

우리는 종종 함수를 실행할때 그 함수 실행에 필요한 파라미터를 넘겨서 실행한다. 근데 중간에 문제가 생겨서 제대로 된 데이터를 넘기지 못했을 때 문제가 발생할 수 있다. 오류는 커녕 undefined로 인식하고 뒤에 코드를 계속적으로 수행할 수 있다. 이럴때 기본 매개 변수를 사용하면 적어도 undefined로 인식되는 일은 없다. 다음 코드를 보면 알 수 있다.

먼저 기본 매개 변수를 사용하지 않았을 때다.

// ES5
const fn1 = (name, age) => {
	return `hi, my name is ${name}. my age is ${age}`;
};

console.log(fn1('carrots')); // hi, my name is carrots. my age is undefined

다음은 기본 매개 변수를 사용했을 때다.

// ES6
const fn1 = (name, age = 20) => {
	return `hi, my name is ${name}. my age is ${age}`;
};

console.log(fn1('carrots')); // hi, my name is carrots. my age is 20

그냥 파라미터가 정상적으로 설정되지 않은 경우 기본 값을 설정하는 개념이라고 보면 된다.

8. Optional Chaining (?. 문법)

상황에 따라 객체가 특정 속성이 있고 없는 경우가 생길 수 있다. 애초에 케이스를 그렇게 구성안하면 되지만, 그럴때 마다 hasOwnProperty 기능을 사용하여 속성이 있는지 체크하고 다음 동작을 수행하게 했어야 했다. ES6부터는 ?. 문법을 사용하여 속성이 있는지 여부를 체크하고 오류없이 안전하게 접근이 가능하다.

다음 코드를 보면 얼마나 불합리한 과정이 필요한지 알 수 있다. 특정 상황에 c : { innerC : 'a' } 가 설정되는 경우가 있다고 가정하자.

// ES5
const obj = { a : 1, b : 2 };
console.log(obj.c.innerC); //Uncaught TypeError: Cannot read properties of undefined (reading 'innerC')

// 바로 다이렉트로 접근하면 그런 속성없다고 오류를 뱉는다. 해당 코드를 정상 수행하게 하려면 다음과 같이 구성해야했다.
if (obj.hasOwnProperty('c')) { // c 속성이 있는지 체크
    if (obj.c.hasOwnProperty('innerC')) { // innerC가 있는지 체크
        console.log(obj.c.innerC); // 출력;;
    }
}

아주 계단식 농작지같은 구성이다. 지금은 체크해야할 뎁스가 두개 뿐이었지만 javascript에서 object안에 여러가지 속성을 선언하고 그 속성안에 속성, 또 그 내부에 속성... 이렇게 트리구조를 띈 데이터 구조를 가질 수 있기 떄문에 뎁스가 추가될때마다 속성이 있는지 체크하는 건 정말이지 고역이다.

다음 ES6에서 Optional Chaining(?. 문법)을 보자.

// ES6
const obj = { a : 1, b : 2 };
console.log(obj?.c?.innerC); //undefined

끝이다. undefined처리가 된다. 적어도 오류를 발생시키지는 않는다는 얘기다. 난 보통 react에서 JSX를 return할때 속성에 따라 화면 제어가 필요한 경우 사용한다.

해당 기능은 여러 방면에서 활용 가능하다.

// ES6
// ?.() 함수 접근
const obj1 = {
   hi() {
       console.log('hi!');
   }
};
const obj2 = {};
obj1.hi?.(); // hi!
obj2.hi?.(); // undefined

// ?.[] key 접근
const obj3 = {
   name : 'carrots'
};
const obj4 = {};
console.log(obj3?.['name']); // carrots
console.log(obj4?.['name']); // undefined

// ?. delete 활용
delete obj3?.name; // obj3에 name 속성이 존재하면 해당 속성을 삭제
console.log(obj3); // {}

개인적으로 정말 편리하다3.

9. Array function (배열 추가 기능)

배열로 이루어 지는 작업이 많아지다 보니 ES6이후 배열에 대한 내부 기능이 많이 추가됐다.

  1. map : 배열을 전개하여 작업 후 새로운 배열로 할당
//ES6
const array = ['apple', 'carrots', 'ggingggang', 'durian'];
const mapResult = array.map((item) => item.length);
console.log(mapResult); // [5, 7, 10, 6]
  1. filter : 조건에 맞는 요소를 찾아 새로운 배열로 할당
//ES6
const array = [1, 5, 10, 13, 30, 42];
const filterResult = array.filter((item) => (item % 5 === 0));
console.log(filterResult); // [5, 10, 30]
  1. reduce : 배열의 각 요소에 대해 주어진 리듀서 함수를 실행하고, 결과값을 반환
//ES6
const array = [1, 5, 10, 13, 30, 42];
const reduceResult = array.reduce((pre, val) => pre + val);

// 배열의 합을 구함
console.log(reduceResult); // 101
  1. find/findIndex : 조건에 맞는 데이터/데이터 index 찾기
// ES6
const array = [1,2,3,4,5,5,5];
const findResult = array.find(item => item === 5);
const findResult2 = array.find(item => item === 7);
const findIndexResult = array.findIndex(item => item === 5);
const findIndexResult2 = array.findIndex(item => item === 7);

// find : 조건에 맞는 데이터 반환
// 조건에 맞는 요소가 있는 경우 : 첫번째 요소만 return
// 조건에 맞는 요소가 없는 경우 : undefined return
console.log(findResult); // 5
console.log(findResult2); // undefined

// findIndex : 조건에 맞는 데이터 index를 반환
// 조건에 맞는 요소가 있는 경우 : 첫번째 요소의 index return
// 조건에 맞는 요소가 없는 경우 : -1 return
console.log(findIndexResult); // 4
console.log(findIndexResult2); // -1
  1. some/every : 조건에 맞는 데이터 여부에 따라 true/false 반환
// ES6
const array = [1,2,3,4,5,5,5];
const someResult = array.some(item => item > 3);
const everyResult = array.every(item => item > 1);

// some : 조건이 맞는 요소가 하나라도 있으면 true, 없으면 false를 반환
console.log(someResult); // true

// every : 배열의 모든 요소가 조건에 맞으면 true, 아니면 false를 반환
console.log(everyResult); // false
  1. flat : 중첩 배열 차원 정리 / 빈공간 삭제
// ES6
const array = [1, [2, 3], [4, 5]];
const array2 = ['carrots', 'apple', , , , , , , , 'durian'];

array.flat(1); // 중첩 배열 차원을 맞춰줌
console.log(array); // [1,2,3,4,5]

array2.flat(); // 빈 값 데이터를 정리해준다.
console.log(array2); // ['carrots', 'apple', 'durian'];

정리하며

Es6 의 추가된기능은 배열에서 같은 단어를 한번만 적어도됨.
리터럴기능에서도 연산자를 안적어도됨.
화살표 함수표현식을 사용함.
데이터를 전개하여 새로운 배열, 객체생성함.

참조 : https://inpa.tistory.com/entry/JS-%F0%9F%9A%80-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%B5%9C%EC%8B%A0-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC-ES6-ES12https://velog.io/@kimhscom/JavaScript-%EC%9E%90%EC%A3%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-ES6-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC

profile
Coding is playing!

0개의 댓글