- ES6 문법(ES2015)
⭐ES6문법
ES(ECMAScript)란 자바스크립트의 표준을 말하며
자바스크립트가 다양한 웹 브라우저에서 공통적으로 잘 작동되도록 표준이 필요해지면서 만들어진 것.
ES6가 가장 큰 변화가 있는 표준.
1) const & let (불변 변수와 가변 변수)
(1) const
불변 변수 선언을 위한 키워드로,
객체와 함께 사용할 때 말고는 값을 다시 할당할 수 없는 변수. (배열이나 객체의 값을 변경하는 것은 가능하다)
보통 const를 사용하며 var 사용보다는 const나 let을 사용.
(2) let
가변 변수 선언을 위한 키워드,
즉, 변경 가능한 변수를 생성할 수 있다. const와 달리 재할당이 가능한 변수.
2) 템플릿 문자열(Template String)
문자열 안에 변수, 연산식을 혼합하여 사용한다.
(1) 작은따옴표( ‘ ‘ ) 대신 백틱( ` )으로 문자열 표현.
(2) 템플릿 문자열에 $를 사용하여 변수나 식 포함 가능.
기존의 코드:
var fruit = { name: '망고', price: 9900 };
var getFruit = function(fruit) {
return fruit.price + '원';
};
var mine = '선택한 과일은 ' + 'fruit.name + '입니다. 가격은 ' + getFruit(fruit) + '입니다.';
템플릿 문자열:
var fruit = { name: '망고', price: 9900 };
var getFruit = function(fruit) {
return ${fruit.price}원;
};
var mine = `선택한 과일은 ${fruit.name}입니다. 가격은 ${getFruit(fruit)}입니다.`;
3) 전개 연산자(Spread Operator)
나열형 자료를 추출, 연결할 때 사용.
사용하려면 배열 또는 객체, 변수명 앞에 마침표 세개(…) 입력.
기존의 코드:
const arr1 = [1,2,3];
const arr2 = [4,5,6];
const combined = arr1.concat(arr2);
전개 연산자:
const arr1 = [1,2,3];
const arr2 = [4,5,6];
const combined = [...arr1, ...arr2];
또다른 예시로 객체의 경우,
기존의 코드:
const obj1 = { one: 1, two: 2 };
const obj2 = { three: 3, four: 4 };
var combined = Object.assign({}, obj1, obj2);
전개 연산자:
const obj1 = { one: 1, two: 2 };
const obj2 = { three: 3, four: 4 };
var combined = {...obj1, ...obj2};
4) 화살표 함수(Arrow function)
화살표 기호 => 로 함수를 선언. function 키워드를 생략하고 인자 블록과 본문 블록 사이에
화살표를 표기하여 사용한다.
기존의 코드:
function addNumber(a,b) {
return a+b;
}
화살표 함수:
const addNumber = (a,b) => {
return a+b;
}
return 키워드를 생략하면
const addNumber = (a,b) => a+b;
5) 클래스(Class)
기존 자바스크립트(ES5까지)에는 클래스가 없었으나 ES6에 추가됨.
(1) 클래스 사용법
① class 키워드: 클래스 정의
② constructor() 생성자 함수
③ new 키워드: 클래스 생성
자세히는 Java Script – Class 장에서 다룬다.
클래스를 사용한 코드:
class addUser {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const user = new addUser('AAA', 24);
console.log(user.name);// AAA
6) 객체 확장 표현식(Enhanced Object property) & 구조 분해 할당(Destructuring assignment)
(1) 객체 확장 표현식(Enhanced Object property)
key-value(키 이름과 값) 데이터 형식의 객체를 확장하여 표현 가능.
객체 내부에서 표현식을 사용하거나 키와 키값을 편리하게 저장할 수 있음.
① 객체 변수를 선언 시 키값을 생략하면 자동으로 키의 이름으로 키값을 지정.
② 객체 생성 블록안에 대괄호로 묶어 그 안에 표현식을 작성 → 계산된 key 값 사용 가능.
③ function 키워드를 생략하여 함수 선언 가능.
기존의 코드:
const a = 0;
const b = 0;
const obj = { a: a, b: b };
console.log(obj);// { a: 0, b: 0 }const ord = "first";
const combined = {};
combined[ord + "Key"] = "value";
console.log(combined);// { firstKey: 'value' }
객체 확장 표현식:
const a = 0;
const b = 0;
const obj = { a, b };
console.log(obj);// { a: 0, b: 0 }const ord = "first";
const combined = { [ord + "Key"]: "value" };
console.log(combined);// { firstKey: 'value' };
(2) 구조 분해 할당(Destructuring assignment)
배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있도록 함.
구조 분해 할당은 함수 인자값을 다루거나 JSON 데이터 변환할 때 유용하며 전개 연산자와 함께 사용됨.
① 배열에서 값을 추출할 때: 인덱스 순서에 맞게 변수 작성
② 변수에 =(선언 부호, 할당 연산자)를 함계 사용하여 기본값 할당 가능
③ 객체에서 값을 추출할 때 키의 이름과 동일반 변수 이름 사용
④ 객체에서 값을 추출할 때 변수에 :(콜론) 부호를 사용하여 새 변수명으로 키값을 할당 가능.
⑤ sqap을 간편하게 구현 가능.
기존의 코드:
const list = [1, 4];
const item1 = list[0];
const item2 = list[1];
const obj = {
key1: "one",
key2: "four",
};
const key1 = obj.key1;
const key2 = obj.key2;
ES6 구조 분해 할당:
const list = [1, 4];
const [item1, item2] = list;
const obj = {
key1: "one",
key2: "four",
};
const { key1, key2, key3 = "eight" } = obj;
7) 비동기 함수
(1) 비동기 처리
작업 시간을 많이 요하는 작업을 처리하는 동안 다른 작업들이 대기 상태인 경우,
다른 작업들을 먼저 진행하고 오래 걸리는 작업과 그 작업에 관련된 작업을 이후에 처리하는 방식.
(2) 프로미스(Promise)
✍🏻 프로미스의 상태 세 가지
- 대기중: 결과를 기다리는 중
- 처리됨 – 이행됨: 수행이 정상적으로 끝남. 결과값을 갖고 있음
- 처리됨 – 거부됨: 수행이 비정상적으로 끝남.
① 프로미스 생성: new 키워드로 생성.
② Promise.resolve 생성: 이행됨 상태인 프로미스 생성
③ Promise.reject 생성: 거부됨 상태인 프로미스 생성.
④ then : 처리됨 상태가 된 프로미스를 처리할 때 사용하는 메소드.
기존의 비동기 함수:
function work1(onDone) {
setTimeout ( () => onDone('작업1 완료.'), 100);
}
function work2(onDone) {
setTimeout ( () => onDone('작업2 완료.'), 200);
}
function urgentWork() {
console.log('긴급 작업');
}
work1(function(msg1) {
console.log('done after 100ms: ' +msg1);
work2(function(msg2) {
console.log('done after 300ms: ' +msg2);
});
});
urgentWork();
우선 순위: (setTimeout이 걸려있지 않으므로) urgentWork() > work1 > work2
지연 작업(work1, work2, …)의 수가 늘어날수록 콜백이 계단으로 형성: 콜백 지옥(callback hell) 발생.
✍🏻콜백 지옥(callback hell)
- 가독성이 떨어짐(코드가 길어진다)
- 코드 수정이 어려움
- 비즈니스 로직을 한눈에 알아보기 어려움
ES6의 비동기 처리:
const work1 = () =>
new Promise((resolve) => {
setTimeout(() => resolve('작업1 완료.'), 100);
});
const work2 = () =>
new Promise((resolve) => {
setTimeout(() => resolve('작업2 완료.'), 200);
});
const urgentWork = () => {
console.log('긴급 작업');
}
const nextWorkOnDone = (msg1) => {
console.log('done after 100ms: ' + msg1);
return work2();
}
work1()
.then(nextWorkOnDone)
.then((msg2) => {
console.log('done after 300ms: ' + msg2);
});
urgentWork();
8) 배열 함수
(1) forEach()
반복문의 순번(i++)과 배열의 크기를 따로 선언하는 과정을 생략할 수 있음.
forEach()가 내장함수이므로 속도 부분으로는 for()보다 더 빠르다.
- 반환값이 없어도 됨
- 문법
arr.forEach(callback(currentValue[, index[, array]])[, thisArg])
callback: 각 요소를 실행할 함수, currentValue와 index, array 세 가지 매개변수를 받음.
currentVaule: 처리할 현재요소
index: 처리할 현재 요소의 index.
array: forEach()를 호출한 배열.
thisArg: callback을 실행할 때 this로 사용하는 값
forEach()를 사용한 코드(1):
const arr = [1, 2, 3, 4, 5];
const odd = [];
arr.forEach(function(num){
if(num%2 == 1) {
odd.push(num);
}
});
console.log(odd);// [1, 3, 5]
forEach()를 사용한 코드(2):
const useQuery = "a=1,b=2,c=3"
function parser(qs) {
const queryString = qs.substr(0);
const splitedStr = queryString.split(',');//splitedStr=['a=1','b=2','c=3']let result = {};
splitedStr.forEach((str) => {
const [key, value] = str.split('=');
result[key]=value;
});
return result;
}
console.log(parser(useQuery));
// {a: '1', b: '2', c: '3'}
(2) map()
배열 요소를 정의된 함수를 통해 새 배열을 만드는 함수.
※ 반환값 필요.
- 문법
arr.map(callback(currentValue[, index[, array]])[, thisArg])
callback: 배열의 모든 요소에 적용되어 새 배열 요소를 생성.
currentVaue: callback이 적용될 현재 요소
index: 처리할 현재 요소의 index
array: map()를 호출한 배열
thisArg: callback을 실행할 때 this로 사용하는 값
map()을 사용한 코드(1):
const arr1 = [1, 2, 4, 8];
const doubleArr = numbers.map((arr1) => {
return arr1 * 2;
});
console.log(doubleArr);// [2, 4, 8, 16]
map()을 사용한 코드(2):
const useQuery = "a=10,b=20,c=30"
function parser(qs) {
const queryString = qs.substr(0);// queryString = a=10,b=20,c=30"const splitedStr = queryString.split(',');// splitedStr = ['a=10', 'b=20', 'c=30']
const result = splitedStr.map((str) => {
const [key, value] = str.split('=');
return {key: key, value: value};// {key: 'a', value: '10'}
});
return result;
}
console.log(parser(useQuery));
/* result = [
{key: 'a', value: '10'},
{key: 'b', value: '20'},
{key: 'c', value: '30'}
];
*/
(3) reduce()
배열의 요소를 순차적으로 순회하며 reducer 함수를 실행하고 하나의 결과값을 반환,
그 결과값은 객체나 배열, 스트링 등이 될 수 있음
- 문법
arr.reduce(callback[, initialValue])
callback: 배열의 각 요소에 대해 실행, 네 가지 인수를 받음.
accumlator(누적값): 누산기. callback의 반환값을 누적.
currentValue(현재값): 처리할 현재 요소
currentIndex(현재 인덱스): 처리할 현재 요소의 index(initialValue를 제공한 경우: 0, 아니면 1부터 시작)
array(현재 배열): reduce()를 호출한 배열.
initialValue(초깃값): callback의 최초 호출에서 첫 번째 인수에 제공하는 값
🌟 reduce의 accumulator와 currentValue
① accumulator(누적값)
accumulator는 callback의 반환값을 누적하는데, 이 누적값이 없거나 초깃값을 제공한 경우
initialValue(초깃값)로 시작함.
② initialValue(초깃값)
initialValue를 설정하지 않았을 경우: accumulator가 배열의 0번째 index, currentVaule가 첫 번째 index
initialValue를 설정한 경우: accumulator가 initialValue, currentVaule가 0번째 index
즉, reduce가 순회하면서 accumulator에 반환값을 누적시키며 하나의 값을 리턴.
- 배열이 비어있는데 초깃값을 제공하지 않을 경우: 에러 발생
reduce()를 사용한 코드(1):
const arr = [1, 2, 3, 4, 5];
const initialValue = 0;
const reduceArr = arr.reduce((accumulator, currentValue) =>
accumulator + currentValue, initialValue
);
console.log(reduceArr);// 15
reduce()를 사용한 코드(2):
const useQuery = "a=1&b=3&c=5"
function parser(qs) {
const queryString = qs.substr(0);// queryString = a=1&b=3&c=5"const splitedStr = queryString.split('&');// splitedStr = ['a=1', 'b=3', 'c=5']
return splitedStr
.map((str) => {
const [key, value] = str.split('=');
return {key, value};
})
.reduce((result, arr) => {
result[arr.key] = arr.value;
return result;
}, {});
}
console.log(parser(useQuery));
// {a: '1', b: '3', c: '5'}