ES6(ECMAScript6)
ES6는 ECMA라는 국제 기구에서 만든 표준문서인 ECMAScript(=ES)의 6번째 개정판 문서에 있는 표준 스펙을 말한다. 6번째 버전이 2015년에 나왔기 때문에 ES2015라고도 한다.
let와const는 var와 다르게 동일하게 모두 블럭 범위이고 ,변수선언과 초기화가 분리되서 진행된다(호이스팅 관련)
// ES5
var MyBtn = document.getElementById('mybtn');
// ES6
const MyBtn = document.getElementById('mybtn');
위의 코드에서 const는 변경되지 않으며 재할당할 수 없다.
let은 새로운 값을 가질 수도 있고 재할당할 수도 있습니다. 변경 가능한 변수가 생성된다.
let name = '철수';
name = '영희';
console.log(name); //영희
화살표함수는 일반함수와 다르게 화살표 함수는 선언할 때 this에 바인딩할 객체가 정적으로 결정되며,
언제나 상위스코프의 this를 가리킨다.생성자 함수로 사용할 수도 없다. 또한 화살표 함수에서는 arguments 변수가 전달되지 않는다
// ES5
function myFunc(name) {
return '안녕' + name;
}
console.log(myFunc('영희'));
// 출력 => 안녕 영희
다음을 사용합니다.
// ES6 화살표 함수
const myFunc = (name) => {
return `안녕 ${name}`;
}
console.log(myFunc('영희')); // 출력 => 안녕 영희
// 또는 화살표를 사용하거나 'return' 키워드를 사용하지 않아도 된다
const myFunc = (name) => `안녕 ${name}`;
console.log(myFunc('영희')); // 출력 => 안녕 영희
// ES5
const myArrary = ['진수', '영철', '영희', 5];
let arr1 = myArrary.map(function(item) {
return item;
});
console.log(arr1); // 출력 => (4) ["진수", "영철", "영희", 5]
// ES6
let arr2 = myArrary.map((item) => item);
console.log(arr2); // 출력 => (4) ["진수", "영철", "영희", 5]
자열을 연결하기 위해 더하기(+) 연산자를 사용할 필요는 없으며, 백틱(`)을 사용하여 문자열 내에서 변수를 사용할 수도 있다.
이전 문법:
// ES5
function myFunc1() {
return '안녕' + name + '너의 나이는' + age + '살 이다!';
}
console.log(myFunc1('영희', 22));
// 출력 => 안녕 영희 너의 나이는 22살 이다!
새로운 ES6 문법 사용:
// ES6
const myFunc = (name, age) => {
return `안녕 ${name}, 너의 나이는 ${age}살 이다!`;
};
console.log(myFunc1('영희', 22));
매개 변수를 쓰지 않은 경우 매개 변수가 이미 기본값에 정의되어 있으므로 정의되지 않은 오류가 반환되지 않는다. 따라서 누락된 매개 변수를 사용하여 함수를 실행할 때 기본 매개 변수 t 값을 사용하고 오류를 반환하지 않는다
const myFunc = (name, age) => {
return `안녕 ${name} 너의 나이는 ${age}살 이니?`;
};
console.log(myFunc1('영희')); // 출력 => 안녕 영희 너의 나이는 undefined살 이니?
위의 함수는 정의되지 않은 상태로 반환된다. 두 번째 매개 변수 age를 지정하지 않았기 떄문이다
그러나 기본 매개 변수를 사용하면 정의되지 않은 매개 변수가 반환되지 않고 매개 변수 할당을 잊어버렸을 때 해당 값이 사용된다
const myFunc = (name, age = 22) => {
return `안녕 ${name} 너의 나이는 ${age}살 이니?`;
};
console.log(myFunc1('영희'));// 출력 => 안녕 영희 너의 나이는 22살 이니?
Spread Opertor는 배열,객체 중괄호 대괄호를 제거해주는 역활을 한다
// 배열
let array2= ['hello', 'world'];
console.log(array2); //['hello', 'world']
console.log(...array2); //hello world
// 변수
let letter= 'hello';
console.log(letter); //hello
console.log(...letter);//h e l l o
// deep copy
var a = [1,2,3];
var b = [4,5];
var c = [...a, ...b];
c = [1,2,3,4,5]// (deep copy할떄 유용)
//등호로 복사를 하면 a와 b 변수는 [1,2,3]을 각각 따로 하나씩 가진게 아니라 값 공유가 일어난다
var a = [1,2,3];
var b = a;
// 객체 property copy
let o1 = { a : 1, b : 2};
let o2 = { a : 3, ...o1 };
console.log(o2);
// 이렇게 a라는 값이 중복이 발생하면 뒤에 오는 a로 적용
// 출력해보면 a : 1 이라는 자료가 담겨짐
// 함수 파라미터 넣을떄
function add(a,b,c){
console.log(a + b + c)
}
let array= [10, 20, 30];
add(...array); //요즘방식
add.apply(undefined, array); //옛날방식// add(array[0], array[1], array[2]);
Rest Parameter는 파라미터값을 배열로 받을 수 있게 해준다.
따라서 파라미터가 몇개가 오는지 미리 정해지 않아도 된다.
// 배열
function printAll( ...args ) { //배열형태로 파라미터가 전달 -> ['seok' , 'woo' , 'jjang']
for(let i =0; i<args.length; i++){
console.log(arg[i]);
}
}
printAll('seok','woo','jjang')
// 출력:
// seok
// woo
// jjang
// args.forEach((arg) => console.log(arg)) 또는
// for(const arg of args) {
// console.log(arg);
// }
// 표현도 가능하다
function fun2(a, b ,...parameter){
console.log(parameter)
}
fun2(1,2,3,4,5,6,7); //[3,4,5,6,7]
//function fun2(a, ...parameter, b){} //에러 :rest parameter는 항상 맨뒤에 써야됨
//function fun2(a, ...parameter, ...parameter2){} //에러:2개 이상 사용할 수 없습니다.
//rest parameter: 파라미터 경우 : []로 씌움
//spread operator:나머지 경우: [],{}을 벋김
Arguments는 함수 파라미터로 들어온 것을 배열로 담아 사용할 수 있게 해준다.
Arguments는 객체는 모든 함수 내에서 이용 가능한 지역 변수이다.
arguments 객체를 사용하여 함수 내에서 모든 인수를 참조할 수 있으며, 호출할 때 제공한 인수 각각에 대한 항목을 갖고 있다. Rest Parameter와 헷갈리니 잘 구분해서 사용하길 바란다.
// 배열
function arg(a,b,c){
console.log(arguments)
}
arg(2,3,4); //[2,3,4]
function 함수(a,b,c){
for (var i = 0; i < arguments.length; i++){
console.log(arguments[i])
}
}
함수(2,3,4);
// 출력:
// 2
// 3
// 4
//arguments: 모든파라미터들을 []에 담음
//rest parameter 이자리에 오는 파라미터를 []에 담음
비구조화를 통해 배열 또는 객체의 값을 새 변수에 더 쉽게 할당할 수 있다.
이전 문법:
// ES5 문법
const contacts = {
famillyName: '이',
name: '영희',
age: 22
};
let famillyName = contacts.famillyName;
let name = contacts.name;
let myAge = contacts.age;
console.log(famillyName);
console.log(name);
console.log(age);
// 출력
// 이
// 영희
// 22
ES6 문법 사용:
// ES6 문법
const contacts = {
famillyName: '이',
name: '영희',
age: 22
};
let { famillyName, name, age } = contacts;
console.log(famillyName);
console.log(name);
console.log(age);
// 출력
// 이
// 영희
// 22
ES5에서는 각 변수에 각 값을 할당해야 하지만 ES6에서는 객체의 속성을 얻기 위해 값을 중괄호 안에 넣는다.
참고: 속성 이름과 동일하지 않은 변수를 할당하면 undefined가 반환된다.
예를 들어, 속성의 이름이 name이고 username 변수에 할당하면 undefined를 반환합니다.
우리는 항상 속성의 이름과 동일하게 변수 이름을 지정해야합니다. 그러나 변수의 이름을 바꾸려면 콜론을 :대신 사용할 수 있습니다.
// ES6 문법
const contacts = {
famillyName: '이',
name: '영희',
age: 22
};
let { famillyName, name: ontherName, age } = contacts;
console.log(ontherName);// 영희
배열의 경우 객체와 동일한 구문을 사용한다. 중괄호를 대괄호로 바꾸면된다.
const arr = ['광희', '지수', '영철', 20];
let [value1, value2, value3] = arr;
console.log(value1);
console.log(value2);
console.log(value3);
// 출력
// 광희
// 지수
// 영철
JavaScript 응용프로그램에서 import 및 export를 사용하면 별도의 재사용 가능한 구성요소를 작성할 수 있다.
export를 사용하면 다른 JavaScript 구성 요소에 사용할 모듈을 내보낼 수 있다. 우리는 그 모듈을 우리의 컴포넌트에 사용하기 위해 가져오기 import를 사용하면 된다.
// ES6
export default function detail(name, age) {
return `안녕 ${name}, 너의 나이는 ${age}살 이다!`;
}
import detail from './detailComponent';
console.log(detail('영희', 20));
import { detail, userProfile, getPosts } from './detailComponent';
console.log(detail('영희', 20));
console.log(userProfile);
console.log(getPosts);
Promise는 ES6의 비동기 코드를 쓰는 방법이다. 예를 들어 API에서 데이터를 가져오거나 실행하는데 시간이 걸리는 함수를 가지고 있을 때 사용할 수 있다.
Promise 개체는 비동기 작업이 맞이할 미래의 완료 또는 실패와 그 결과 값을 나타낸다.
매개변수resolve 와 reject 는 함수로서 호출되면 promise 를 이행하거나 거부한다.
이 둘을 이용하여 비동기 작업이 모두 끝나면 resolve 를 호출해 이행하고, 중간에 오류가 생기면 reject 를 이용해 거부하게 된다.
우선 Promise 는 매개변수로 executor 를 받게 된다. executor 는 resolve 와 reject 인수를 전달할 실행함수이다.
const promise = new Promise((resolve, reject)=>{});
console.log(promise);// Promise { <pending> }
const promise2 = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve("resolve");
}, 3000);
});
console.log(promise2);
setInterval(()=>{
console.log(promise2);
}, 1000);
/*
Promise { <pending> }
Promise { <pending> }
Promise { <pending> }
Promise { 'resolve' }
Promise { 'resolve' }
Promise { 'resolve' }
*/
// Promise 의 then 과 catch
// then
// promise 가 종료가 되면 resolve 에 들어간 값을 받을 수 있습니다.
const promise3 = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve("resolve");
}, 3000);
});
promise3.then(value => console.log(value));
// 3초 후에 결과가 출력
// resolve
// catch
// 하지만 reject 된 경우에는 then 으로 받을 경우, 에러가 발생합니다.
const promise4 = new Promise((resolve, reject)=>{
setTimeout(()=>{
reject("reject");
}, 3000);
});
promise4.then(value => console.log(value)); // UnhandledPromiseRejectionWarning: reject
// 이 때 catch 를 사용하여 에러를 잡아줄 수 있습니다.
//then,cathch는 같이 실행될수x
promise4.then(result => console.log(result)).catch(error => console.log(error));
// 3초 후에 결과가 출력
// reject
//Chaining Promise
// 상황에 따라 promise 를 여러 번 사용해야 하는 경우가 존재합니다.
// API 로 data 를 받아오기 위해서 promise 를 사용하고
// 받아온 데이터의 암호를 풀기 위해서 promise 를 한 번 더 사용할 수 있습니다.
// 이를 Chaining Promise 라고 합니다.
const promise5 = new Promise((resolve, reject)=>{
resolve(2);
});
promise5.then(result => {
const output = result+1;
console.log(output); // 3
return output;
})
.then(result => {
const output = result+1; // 4
console.log(output);
return output;
})
// 그런데 중간의 chain 에서 에러가 발생하면 어떻게 될까요?
// 이를 해결하기 위해서 각 then 마다 catch 를 넣어줘야 할까요?
// 다행히도 catch 는 한 번의 사용으로 모든 then 에 대해서 해결할 수 있습니다. ->하지만 어디서 에러났는지 판단하기 힘듬 (async await의 탄생배경)
const promise6 = new Promise((resolve, reject)=>{
resolve(2);
});
const plusOne = num => num + 1;
promise
.then(plusOne)
.then(plusOne)
.then(plusOne)
.then(()=> {
throw Error("error")
})
.then(result => console.log(result))
.catch(error => console.log(error));
// Promise all
// all() 은 주어진 모든 Promise 를 실행한 후 진행되는 하나의 Promise 를 반환합니다.
// 3개의 promise 에 대해 이들을 array 로 all 에 넘겨주면 allPromise 는 3개의 promise가 모두 끝날 때 까지 기다린 후에 이들의 결과값을 array로 반환하게 됩니다.
const p1 = new Promise(resolve => {
setTimeout(resolve, 2000, "First");
})
const p2 = new Promise(resolve => {
setTimeout(resolve, 1000, "Second");
})
const p3 = new Promise(resolve => {
setTimeout(resolve, 3000, "Third");
})
const allPromise = Promise.all([p1,p2,p3]);
allPromise.then(values => console.log(values));// [ 'First', 'Second', 'Third' ]
// 이 중 하나의 promise 에서 에러가 발생한다면 어떻게 될까요?
// allPromise 는 모든 promise 에 대해서 결과값을 받아와야 하는데 그러지 못하므로 에러가 발생하게 됩니다
//이 경우 catch 는 각 promise 에 해줄 필요는 없고, allPromise 에 대해서만 해주면 됩니다.
const allPromise2 = Promise.all([p1,p2,p3]);
allPromise2
.then(values => console.log(values))
.catch(error => console.log(error));
// First reject
// Promise race
// race() 는 주어진 Promise 중 가장 먼저 완료된 것의 결과값을 이행하거나 거부합니다.
// 위에서 살펴본 all 과 사용하는 방법은 같습니다.
// p1 은reject 하고 있지만 결과는 Second 가 나옵니다.
// p2 는 1초만에 끝나기 때문에 그 결과값을 받아 바로 출력해버리는 것이죠.
const p11 = new Promise((resolve, reject) => {
setTimeout(reject, 2000, "First reject");
})
const p22 = new Promise(resolve => {
setTimeout(resolve, 1000, "Second");
})
const p33 = new Promise(resolve => {
setTimeout(resolve, 3000, "Third");
})
const allPromise3 = Promise.race([p11,p22,p33]);
allPromise3
.then(values => console.log(values)) // Second
.catch(error => console.log(error));
// Promise finally
// finally() 는 Promise 가 resolve 되던 reject 되던 상관없이 지정된 함수를 실행합니다.
// 이를 통해 promise 의 결과에 상관없이 동작을 해야할 때 유용하게 구현할 수 있습니다.
// 해당 예시가 중간에 에러가 발생하고 이를 catch 로 잡아주었어도 finally 는 실행되어 end 를 출력합니다.
const p5 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, "First");
});
p5
.then(result => console.log(result))// First
.finally(()=>console.log("end")); // end
class는 객체 지향 프로그래밍(OOP)의 핵심이다. 코드를 더욱 안전하게 캡슐화할 수 있습니다. class를 사용하면 코드 구조가 좋아지고 방향을 유지합니다.
class를 만들려면 class 키워드 뒤에 두 개의 중괄호가 있는 class 이름을 사용한다.
class myClass {
constructor() {
}
}
이제 new 키워드를 사용하여 class 메서드와 속성에 액세스할 수 있습니다.
class myClass {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
const user = new myClass('영희', 22);
console.log(user.name); // 영희
console.log(user.age); // 22
다른 class에서 상속하려면 extends 키워드 다음에 상속할 class의 이름을 사용합니다.
class myClass {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`안녕 ${this.name} 너의 나이는 ${this.age}살이다`);
}
}
// myClass 메서드 및 속성 상속
class UserProfile extends myClass {
userName() {
console.log(this.name);
}
}
const profile = new UserProfile('영희', 22);
profile.sayHello(); // 안녕 영희 너의 나이는 22살이다.
profile.userName(); // 영희