ES란 ECMAScript의 약자이며 자바스크립트의 표준, 스펙을 나타내는 용어다.
ES6+는 2015년에 개정된 javascript 스펙 ES6를 포함한 상위 스펙을 통칭하는 말이다.
ES5 기준으로 개발을 시작했던 나로써는 ES6를 기점으로 javascript의 코드가 굉장히 간결하고 명확해졌다고 생각한다. 개발 업계는 역시 게을러지면서 발전한다..
ES6+의 추가된 기능은 다음과 같다. 모든 기능을 전부 나열하기엔 양도 많고 범위도 정확하지 않아 내가 주로 사용하는 기능만 정리해본다. ES6에서 추가된 Promise와 classes는 다음 글에서 다루겠다.
드럽게 많네..
해당 내용은 내 게시글에 정리되어 있다. 한마디로 요약하자면 변수, 상수 선언 방식이 추가된 것인데 바쁘니 다음 링크를 참조하자. >> var, let, const 분석
화살표 함수 선언식은 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 안쓰는게 전부인 기능이다. 일단 간지나니까 그냥 쓰자.
변수와 문자열을 병합할때 + 연산자를 사용해서 문자열을 생성한 경험이 모두 있을 것 이다.
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}`;
중간 중간 +연산자를 쓸 필요없이 수행 가능하다.
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 : '당근먹기' };
하나 하나 지정해야 했던 과거의 지저분한 코드가 보다 간결해졌다.
배열과 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;
개인적으로 정말 편리하다.
기존엔 객체나 배열을 복사해서 쓸때 요소들을 전개해서 복사했어야 했다. 개발을 하다보면 정말이지 고역이다. 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]
// ES6
const array = ['apple', 'carrots', 'ggingggang', 'durian'];
const [ value1, value2, ...restValue ] = array; // 비구조화로 각 요소를 설정
console.log(restValue); // ['ggingggang', 'durian']
개인적으로 정말 편리하다2.
우리는 종종 함수를 실행할때 그 함수 실행에 필요한 파라미터를 넘겨서 실행한다. 근데 중간에 문제가 생겨서 제대로 된 데이터를 넘기지 못했을 때 문제가 발생할 수 있다. 오류는 커녕 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
그냥 파라미터가 정상적으로 설정되지 않은 경우 기본 값을 설정하는 개념이라고 보면 된다.
상황에 따라 객체가 특정 속성이 있고 없는 경우가 생길 수 있다. 애초에 케이스를 그렇게 구성안하면 되지만, 그럴때 마다 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.
배열로 이루어 지는 작업이 많아지다 보니 ES6이후 배열에 대한 내부 기능이 많이 추가됐다.
//ES6
const array = ['apple', 'carrots', 'ggingggang', 'durian'];
const mapResult = array.map((item) => item.length);
console.log(mapResult); // [5, 7, 10, 6]
//ES6
const array = [1, 5, 10, 13, 30, 42];
const filterResult = array.filter((item) => (item % 5 === 0));
console.log(filterResult); // [5, 10, 30]
//ES6
const array = [1, 5, 10, 13, 30, 42];
const reduceResult = array.reduce((pre, val) => pre + val);
// 배열의 합을 구함
console.log(reduceResult); // 101
// 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
// 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
// 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-ES12
https://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