ES2015+
2015년 자바스크립트 문법에 매우 큰 변화가 있었다. ES6가 등장한 것이다.
현재는 ES2020까지 나왔다. 우선 ES6 내용을 정리하고 나머지도 정리해보자.
const, let
자바스크립트를 배울 때는 var로 변수를 선언하는 방법부터 배운다.
하지만 이제 const와 let이 대체한다. const와 let이 공통적으로 가지는 특징은 블록 스코프이다.
블록 스코프란 해당 블록에서만 접근할 수 있다는 것이다. 함수 스코프 대신 블록 스코프를 사용함으로써 호이스팅 같은 문제도 해결되고 코드 관리도 수월해졌다.
const는 한 번 값을 할당하면 다른 값을 할당할 수 없다. 또한, 초기화할 때 값을 할당하지 않으면 에러가 발생한다.
템플릿 문자열
백틱을 이용한 문자열이다. 중간에 변수를 사용하거나 이스케이프 문자를 사용해야 하는 불편함을 해결해준다.
const num1 = 1;
const num2 = 2;
const num3 = 3;
const string = `${num1} 더하기 ${num2}는 ${num3}`;
객체 리터럴
객체 리터럴에 편리한 기능들이 추가되었다.
: 과 fuction을 사용하지 않고 바로 함수를 연결할 수 있다. 또한 속성명과 변수명이 동일한 경우 한 번만 써도 되게 변경되었다. 또한 객체의 속성명은 동적으로 생성할 수 있다.
const newObject = {
sayJS() {
console.log('JS');
},
sayNode,
[es + 6]: 'ES6'
};
화살표 함수
function을 정의하는 방법이다.
const add1(x, y){
return x + y;
}
const add2 = (x, y) => {
return x + y;
};
const add3 = (x, y) => x + y;
const add4 = (x, y) => (x + y);
const not = x => !x;
매개변수가 하나라면 괄호를 사용하지 않아도 무방하다. 또한 함수 내부에 return문 밖에 없는 경우에는 return을 생략할 수 있다. 그리고 주의해야 할 점이 있다. this의 사용이다. 화살표 함수는 상위 스코프의 this를 그대로 물려받아 사용한다.
구조분해 할당
구조분해 할당을 사용하면 객체와 배열로부터 속성이나 요소를 쉽게 꺼낼 수 있다.
const candyMachine = {
status: {
name: 'node',
count: 5,
},
getCandy(){
this.status.count--;
return this.status.count;
},
};
const { getCandy, status: { count } } = candyMachine;
const array = ['node', {}, 10, true];
const [node, obj, ,bool] = array;
이런 식으로 해당하는 요소를 대입할 수 있다.
클래스
프로토타입 기반으로 동작하는 클래스이다.
var Human = function(type){
this.type = type || 'human';
};
Human.isHuman = function(human){
return human instanceof Human;
}
Human.prototype.breathe = function(){
alret('h-a-a-a-m');
}
var Zero = function(type, firstName, lastName){
Human.apply(this, argument);
this.firstName = firstName;
this.lastName = lasgName;
};
Zero.prototype = Object.create(Human.prototype);
Zero.prototype.constructor = Zero;
Zero.prototype.sayName = function(){
alert(this.firstName+ ' ' + this.lastName);
};
var oldZero = new Zero('human', 'Zero', 'Cho');
Human.isHuman(oldZero);
이것을 class로 바꾸어보자.
class Human {
constructor(type = 'human'){
this.type = type;
}
static isHuman(human){
return human instanceof Human;
}
breathe(){
alert('h-a-a-a-m');
}
}
class Zero extands Human{
constructor(type, firstName, lastName){
super(type);
this.firstName = firstName;
this.lastName = lastName;
}
sayName(){
super.breathe();
alert(`${this.firstName} ${this.lastNa,e}`);
}
}
const newZero = new Zero('human', 'Zero', 'Cho');
Human.isHuman(newZero);
프로미스
자바스크립트와 노드에서는 주로 비동기를 접한다. 특히 콜백 함수를 자주 사용한다. ES6부터는 콜백 대신 프로미스 기반으로 재구성되며 콜백 지옥 현상을 극복했다.
const condition = true
const promise = new Promise((resolve, reject) => {
is(condition){
resolve('성공');
}else{
reject('실패');
}
});
promise
.then((message) => {
console.log(message);
})
.catch((error) => {
console.log(error);
})
.finally(() => {
console.log('무조건');
});
new Promise로 프로미스를 생성할 수 있고, 그 내부에 resolve와 reject를 매개변수로 갖는 콜백 함수를 넣는다.
프로미스 내부에서 resolve가 호출되면 then이 실행되고 reject가 호출되면 catch가 실행된다.
finally는 무조건 실행된다. then 안에서도 또 다른 프로미스를 생성할 수 있다.
Promise.all은 모두 resolve가 돼야 다음 then으로 넘어간다. 하나라도 reject가 되면 catch로 넘어간다.
async/await
ES7에서 추가된 편리한 기능이다. 프로미스로 콜백 지옥을 해결했지만 then, catch가 반복되어 코드가 복잡하다.
이를 async/await으로 깔끔하게 만들 수 있다.
function findAndSaveUser(Users){
Users.findOne({})
.then((user) => {
user.name = 'zero';
return user.save();
})
.then((user) => {
return Users.findOne({ gender: 'm' });
})
.then((user) => {
//실행
})
.catch(err => {
console.error(err);
});
}
이를 async/await으로 바꿔보자.
async function findAndSaveUser(Users){
let user = await Users.findOne({});
user.name = 'zero';
user = await user.save();
user = await Users.findeOne({gender: 'm'});
}
프로미스가 resolve 될 때까지 기다린 뒤 다음 로직으로 넘어간다.
error를 처리하는 부분이 없으므로 추가 작업이 필요하다.
async function findAndSaveUser(Users){
try{
let user = await Users.findOne({});
user.name = 'zero';
user = await user.save();
user = await Users.findeOne({gender: 'm'});
}catch(error){
console.error(error);
}
}
화살표 함수에도 적용 가능하다.
프로트엔드 자바스크립트
HTML에서 script 태그 안에 작성하는 자바스크립트를 알아보자.
AJAX(Asynchronous Javascript And XML)
AJAX는 비동기적 웹 서비스를 개발할 때 사용하는 기법이다. 페이지 이동 없이 서버에 요청을 보내고 응답을 받는 기술이다. 보통 AJAX 요청은 jQuery나 axios 같은 라이브러리를 이용해서 보낸다.
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
axios.get('https://www.zerocho.com/api/get')
.then((result) => {
console.log(result);
console.lof(result.data);
})
.catch((error) => {
console.error(err);
});
</script>
위와 같이 get 요청을 보낼 수 있다.
FormData
HTML form 태그의 데이터를 동적으로 제어할 수 있는 기능이다. 주로 AJAX와 함께 사용된다.
const formData = new FormData();
formData.append('name', 'GR8');
formData.append('item', 'orange');
formData.append('item', 'melon');
formData.has('item'); //true
formData.has('money'); //false
formData.get('item'); //orange
formData.getAll('item'); //['orange', 'melon']
formData.append('test', ['hi', 'zero']);
formData.get('test'); //hi, zero
formData.delete('test');
formData.get('test'); //null
formData.set('item','apple');
formData.getAll('item'); // ['apple']
(async() => {
try{
const formData = new FormData();
formData.append('name', 'GR8');
formData.append('birth', 1997);
const result = await axios.post('https://www.zerocho.com/api/post/formdata', formData);
console.log(result);
console.log(result.data);
}catch(err){
console.error(err);
}
})();
encodeURIComponent, decodeURIComponent
AJAX 요청을 보낼때 한글이 들어가는 주소는 에러가 발생하는 경우가 있다. 이때 window 객체의 매서드인 encodeURIComponent 메서드를 사용해서 변경해 줘야 한다.
(async () => {
try{
const result = await axios.get(`https://www.zerocho.com/api/search/${encodeURIComponent('노드')}`);
console.log(result);
console.log(result.data);
}catch(err){
console.error(err);
}
})();
변환된 한글주소를 다시 복구하려면 decodeURIComponent를 사용하면 된다.
데이터 속성과 dataset
데이터를 내보낼 때 고려할 점들이 여러 개 있다. 그중에 첫 번째는 보안이다.
비밀번호 같은 정보는 절대 내보내면 안 된다.
이를 구분할 수 있는 것이 데이터 속성이다.
<ul>
<li data-id="1" data-user-job="programmer">zero</li>
<li data-id="2" data-user-job="designer">nero</li>
<li data-id="3" data-user-job="programmer">hero</li>
<li data-id="4" data-user-job="ceo">kero</li>
</ul>
<script>
console.log(document.querySelector('li').dataset);
</script>
data-로 시작하는 것들을 데이터 속성이라 한다. dataset 속성을 통해 첫 번째 li 태그의 데이터 속성에 접근한 것이다.
data-라는 접두어는 사라지고 뒤의 이름으로 관리가 된다.