프로그래밍 언어/자바스크립트

ES6 문법 정리(중요)

낙산암 2022. 1. 9. 00:41

1. const

6이전에는 var 키워드가 전부 였으나, let 과 const를 제공하기 시작함.

 

var study = true;
study = false;
console.log(study) // false

 

const study = true;
study = false;
//	Uncaught TypeError가 발생함

한번 활당후 다시 할당이 불가능 함.

 

2. let

var study = "자바스트립트";

if(study){
	var study = "리액트";
	console.log('공부하자', study); // 공부하자 리액트
}

console.log('재밌다', study); // 재밌다 리액트

 

 if문 안의 study값을 변경하면 if밖의 study도 변경됨.(호이스팅)

 let을 사용하면 변수 영역을 코드 블록 안으로 한정시킬수 있다.

 

var study = "자바스트립트";

if(study){
	let study = "리액트";
	console.log('공부하자', study); // 공부하자 리액트
}

console.log('재밌다', study); // 재밌다 자바스크립트

 

이제는 무조건 let을 써야 함.

 

3. 템플릿 문자열

 

전통적인 문자열 연결은 더하기 기호(+)로 문자열과 변수를 서로 이어붙이는 방식

 

console.log(lastname + ", " + firstname + " " + middlename);

 

템플릿에서는 ${ }를 사용해 문자열 안에 변수를 집어넣을 수 있기 때문에 문자열을 단 하나만 사용해도 된다.

 

console.log(`${lastname}, ${firstname} ${middlename}`);

 

`
${firstname} 님께,

${event} 티켓 ${qty}건을 구매해주셔서 감사합니다.

주문 상세 정보 :
	${lastname} ${firstname} ${middlename}
    ${qty} x $${price} = $${qty*price}	공연 : ${event}
    
공연 30분 전까지 배부처에서 티켓을 수령하시기 바랍니다.
감사합니다 :)

${ticketAgent} 드림
`

이제는 문자열 안의 공백 문자가 제대로 처리되기 때문에 이해하기 쉽게 정렬된 HTML을 코드로 넣을 수 있다.

 

4. 디폴트 파라미터

 

ES6 명세에도 디폴트 파라미터가 추가

 

function logActivity(name="EZ", activity="서핑"){
	console.log(`${name}은(는) ${activity}을(를) 좋아합니다.`);
}
var dafaultPerson = {
	name: {
    	first : "Z",
        last : "E",    
    },
    favActivity: "서핑"
}

function logActivity(p = dafaultPerson){
	console.log(`${p.name.first}은(는) ${favActivity}을(를) 좋아합니다.`);
}

logActivity 함수를 호출하면서 인자를 지정하지 않아도 디폴트 값을 사용해서 함수가 정상적으로 실행된다.
문자열뿐 아니라 어떤 타입의 값도 디폴트 값으로 사용할 수 있다.

 

5.화살표 함수

 

이를 사용하면 function 키워드 없이도 함수를 만들 수 있으며, return을 사용하지 않아도 식을 계산한 값이 자동으로 반환된다.

 

var lordify = function(name) {
	return `열심히 공부하는 ${name}`;
}

console.log(lodify("EZ")); // 열심히 공부하는 EZ

화살표 함수 방식

var lodify = name => `열심히 공부하는 ${name}`;

 

ES6 트랜스파일링

모든 웹브라우저가 ES6를 지원하지는 않고, 지원하더라도 모든 기능을 지원하지 않는 경우가 많다.
그러니 브라우저에서 ES6코드를 실행하기 전에 ES5로 컴파일하면 ES6가 제대로 작동하도록 보장할 수 있다.
이런 변환을 트랜스파일링(transpiling)이라고 한다.
가장 유명한 트랜스파일링 도구로는 바벨(Babel)이 있다.

트랜스파일링으로 브라우저가 최신 자바스크립트 기능을 지원할 때 까지 기다리지 않아도 바로 사용할 수 있게 됐다!
트랜스파일링은 한 버전의 자바스크립트 코드를 더 많은 브라우저가 이해할 수 있는 다른 버전의 자바스크립트 구문으로 변환하는 것이다.
게다가 이제는 자바스크립트에서 소스코드가 생겨났다.
이 말은 브라우저에서 직접 실행할 수 있는 파일이 프로젝트에 들어있는 경우도 있다는 뜻이다.

const add = (x=5, y=10) => console.log(x+y);

이 코드를 트랜스파일러로 변환하면 다음과 같은 출력이 생긴다.

"use strict";

var add = function add(){
	var x = arguments.length <= 0 || arguments[0] === undifined ? 5 : arguments[0];
    var y = arguments.length <= 1 || arguments[1] === undifined ? 10 : arguments[1];
	return console.log(x+y);
};

트랜스파일러는 use strict 선언을 맨 위에 추가해서 코드가 엄격한 모드에서 실행되도록 만든다.
x와 y 파라미터의 디폴트 값은 arguments 배열로 처리된다.
이렇게 만들어진 자바스크립트는 다양한 브라우저에서 사용 가능하다.

인라인 바벨 트랜스파이럴를 사용하면 브라우저에서 자바스크립트를 직접 트랜스파일 할 수도 있다.
browser.js 파일을 포함시키고(HTML의 script태그 사용), 변환하고 싶은 코드의 script 태그에 type="text/babel"을 지정하면 된다.

<div id="output"></div>
<!--바벨 로딩-->
<script src = "https://unpkg.com/babel-stendalone@6/babel.min.js"></script>
<!--변환할 코드를 script태그 안에 넣기 -->
<script type="text/babel">
const getMessage = () => "Hello World";
document.getElementById('output').innerHTML = getMessage();
</script>
<!--파일에 있는 소스 코드를 트랜스파일링 하기-->
<script src="script.js" type="text/babel">

 

ES6 객체와 배열

 

ES6는 객체와 배열을 다루는 방법과, 객체와 배열 안에서 변수영역을 제한하는 방법을 다양하게 제공한다.
그러한 기능으로 구조분해, 객체 리터럴 개선, 스프레드 연산자 등이 있다.

 

1. 구조 분해를 사용한 대입

var sandwich = {
  bread : "플랫 화이트",
  meat : "베이컨",
  topping : ["치즈","상추","칠리소스"]
}

var {bread, meat} = sandwich;
console.log(bread, meat); // 플랫 화이트 베이컨

위 코드는 sandwich를 분해해서 bread와 meat필드를 같은 이름의 변수에 넣어준다.
두 변수의 값은 sandwich에 있는 같은 이름의 필드 값으로 초기화 되지만, 두 변수를 변경해도 원래의 필드 값은 바뀌지 않는다.

 

var {bread, meat} = sandwich;

bread = "식빵"
meat = "삼겹살"

console.log(bread, meat); // 식빵 삼겹살
console.log(sandwich.bread, sandwich.meat); // 플랫 화이트 베이컨

 

객체를 분해해서 함수의 인자로 넘길 수도 있다.

var study = person => {
  console.log(`오늘도 공부하는 ${person.firstname}`);
}

var person = {
  firstname : "zeze",
  lastname : "E"
}

study(person); // 오늘도 공부하는 zeze

객체의 필드에 접근하기 위해 점(.)과 필드이름을 사용하는 대신 person에 필요한 값을 구조분해로 가져올 수도 있다.

var study = ({firstname}) => {
  console.log(`오늘도 공부하는 ${firstname}`);
}

study(person); // 오늘도 공부하는 zeze

배열을 구조분해해서 원소의 값을 변수에 대입할 수도 있다.
배열의 첫번째 원소를 변수에 대입하고싶다고 가정하자.

var [firstResort] = ["용평","평창","강촌"];

console.log(firstResort); // 용평

불필요한 콤마(,)를 사용해 생략하는 리스트 매칭을 사용할 수도 있다.
무시하고 싶은 원소 위치에 콤마를 넣으면 리스트 매칭이 된다.
위 배열에서 첫 두 원소를 콤마로 대치하면 다음과 같다.

var [,,thirdResort] = ["용평","평창","강촌"];

console.log(thirdResort); // 강촌

 

2. 객체 리터럴 개선

객체 리터럴 개선(object literal enhancement)은 구조분해의 반대라 할 수 있다.
객체 리터럴 개선은 구조를 다시 만들어내는 과정 또는 내용을 한데 묶는 과정이라 할 수 있는데 이 구조를 사용하면 현재 영역에 있는 변수를 객체의 필드로 묶을 수 있다.

var name = "백두산";
var elevation = 2744; // 높이(단위: 미터)

var funHike = {name, elevation};

console.log(funHike) // {name: "백두산", elavation: 2744}

이제 funHike에는 name과 elevation이라는 필드가 들어있다.
객체 리터럴 개선 또는 객체 재구축으로 객체 메서드를 만드는것도 가능하다!

var name = "백두산";
var elevation = 2744;
var print = function(){
  console.log(`${this.name}의 높이는 ${this.elevation}m 입니다.`);
}
var funHike = {name, elevation, print}

funHike.print() //	백두산의 높이는 2744m 입니다.

이 때 객체 키에 접근하기 위해 this를 사용했다는 것을 유의하자.
객체 메서드를 정의할 때 더이상 function 키워드를 사용하지 않아도 된다!

 

3. 스프레드 연산자

스프레드 연산자(spread operator)는 세 개의 점(...)으로 이루어진 연산자로, 몇 개의 다른 역할을 담당한다.
먼저 배열의 내용을 조합할 수 있다. 예를 들어 두 배열이 있다면 스프레드 연산자를 적용하여 두 배열의 모든 원소가 들어간 세 번째 배열을 쉽게 만들 수 있다.

var food = ["닭갈비", "닭꼬치", "닭강정"]
var drink = ["소주", "맥주"]
var ezFavorite = [...food, ...drink]

console.log(ezFovorite.join(', '); // 닭갈비, 닭꼬치, 닭강정, 소주, 맥주

food와 drink에 포함된 모든 원소가 ezFavorite이라는 새 배열에 들어간 것을 확인할 수 있다.

이 스프레드 연산자로 해결할 수 있는 문제를 보자!
food 배열의 마지막 원소를 변수에 담고싶다고 가정하고 Array.reverse 메서드를 사용해 배열을 뒤집고 구조 분해를 사용해 첫 번째 원소를 변수에 넣어보자.

var food = ["닭갈비", "닭꼬치", "닭강정"]
var [last] = food.reverse();

console.log(last);	// 닭강정
console.log(food.join(', '));	// 닭강정, 닭꼬치, 닭갈비

마지막 콘솔에 찍어서 나온 결과와 같이 원본 배열도 변경되는 것을 확인할 수 있다.
하지만 스프레드 연산자를 사용하면 원본 배열을 변경하지 않고 복사본을 만들어서 뒤집을 수 있다!(와 나 이거때문에 코딩테스트에서 고생했었는데 ㅠ)

var food = ["닭갈비", "닭꼬치", "닭강정"]
var [last] = [...food].reverse();

console.log(last);	// 닭강정
console.log(food.join(', '));	// 닭갈비, 닭꼬치, 닭강정

스프레드 연산자를 사용해 배열의 원소를 복사했기 때문에 원본인 food는 변경되지 않고 그대로 남아있다.
따라서 나중에 필요할 때 food 연산자를 재사용 할 수 있당!

또한 배열의 나머지 원소를 얻을 수도 있다.
예제를 보시죠,,

var food = ["닭갈비", "닭꼬치", "닭강정"]
var [last] = [...food].reverse();

console.log(last);	// 닭강정
console.log(food(, ));	// 닭갈비, 닭꼬치, 닭강정

그만 쓰고싶은데 예제가 또 있다.
함수의 인자를 배열로 모을 수도 있다고 한다,,
아래는 'n개의 인자를 스프레드 연산자를 사용해 배열로 모은 다음 그 배열을 사용해 여러가지 내용을 콘솔 메시지로 찍는 함수'를 보여주는 예제다.

function directions(...args){
  var [start, ...remaining] = args;
  var [finish, ...stops] = remaining.reverse();
  
  console.log(`${args.length} 도시를 운행합니다.`);
  console.log(`${start}에서 출발합니다.`);
  console.log(`목적지는 ${finish}입니다.`);
  console.log(`중간에 ${stops.length}군데 들립니다.`);
}

  directions("서울", "수원", "천안", "대전", "대구", "부산");

directions 함수는 스프레드 연산자를 사용해 인자를 받는다.
첫번째 인자는 start 변수에 대입된다.
마지막 인자는 finish 변수에 Array.reverse를 사용하여 대입된다.
그 후 args 배열의 length를 사용해 몇개의 도시를 운행하는지 보여주고, 목족지로 가는동안 들러야 하는 도시의 수는 args 배열에서 2(출발지와 도착지)를 뺀 것이다.
directions 함수의 임의 개수는 경유 도시를 넘길 수 있기 때문에 이런 기능은 매우 편리하다!

마지막으로,,(우욱) 연산자를 객체에 사용할 수도 있다.
스프레드 연산자를 객체에 사용하는 방법은 배열에 사용한 것과 비슷하다,,
바로 예제를 보자.

var morning = {
  breakfast : "샌드위치",
  lunch : "닭갈비"
};

var dinner = "간장불고기";

var meals = {
  ...morning,
  dinner
};

console.log(meals);
// {brackfast: "샌드위치", lunch: "닭갈비", dinner: "간장불고기"}

 

클래스

이전 자바스크립트에는 공식적으로 클래스가 없었고 타입은 함수로 정의했다.
ES6에서는 클래스 선언이 추가되었다.하지만 자바스크립트는 여전히 기존 방식으로 작동한다.
함수는 객체며 상속은 프로토타입을 통해 처리된다.

클래스를 정의하면 new 키워드를 사용해 해당 클래스의 새로운 인스턴스를 만들 수 있다.
그 후 인스턴스의 메서드를 호출할 수 있다.
(클래스 이름의 첫글자는 대문자로 시작하는 관습이 있당)

class Vacation{
  constructor(destination, length){
    this.destination = destination;
    this.length = length;
  }
  
  print(){
    console.log(`${this.destination}은(는) ${this.length}일 걸립니다.`);
  }
}

const trip = new Vacation("칠레 산티아고", 7);

console.log(trip.print()); // 칠레 산티아고은(는) 7일 걸립니다.

클래스 객체를 만든 뒤에는 새로운 객체를 생성하기 위해 원하는만큼 new를 호출할 수 있다.
클래스를 확장할 수도 있다. 기존 클래스(부모클래스)를 확장한 새로운 클래스(자식클래스)는 상위 클래스의 모든 프로퍼티와 메서드를 상속한다.
이렇게 상속한 프로퍼티나 메서드를 하위 클래스 선언 안에서 변경할 수도 있다.

위 예제에서 쓴 Vacation을 여러가지 휴가 타입을 정의하기 위한 추상 클래스로 사용할 수도 있다.
예를 들어 아래 예제의 Expedition은 Vacation 클래스를 확장하여 장비를 표현하는 프로퍼티(gear)를 더 가진다.

class Expedition extends Vacation {
  constructor(destination, length, gear){
    super(destination, length);
    this.gear = gear;
  }
  
  print(){
    super.print();
    console.log(`당신의 ${this.gear.join("와(과) 당신의 ")}를(을) 가져오십시오.`);
  }
}

const trip2 = new Expedition("한라산", 3, ["카메라", "생수", "선글라스"]);

trip2.print();
// 한라산은(는) 3일 걸립니다.
// 당신의 카메라와(과) 당신의 생수와(과) 당신의 선글라스를(을) 가져오십시오.

ES6 모듈

자바스크립트 모듈(module)은 다른 자바스크립트 파일에서 쉽게 불러서 활용할 수 있는 재활용 가능한 코드 조각을 말한다.
이전에는 자바스크립트를 모듈화 하는 방법이 import와 export를 처리하는 라이브러리를 활용하는 것 뿐이었지만, ES6부터는 자바스크립트 자체에서 모듈을 지원하기 시작했다.

자바스크립트는 각각의 모듈을 별도의 파일로 저장한다.
모듈을 만들고 외부에 익스포트하는 방법에는
1. 한 모듈에서 여러 자바스크립트 객체를 외부에 노출시키는 방법
2. 모듈당 하나의 자바스크립트 객체를 노출시키는 방법
이 있다.

  1. 한모여자(한 모듈에서 여러 자바스크립트) 예제
export const print(message) => log(message, new Date());

export const log(message, timestamp) => console.log(`${timestamp.toString()}: ${message}`);

다른 모듈에서 사용하도록 이름(함수, 객체, 변수, 상수 등이 될 수도 있음)export할 수 있다.(위 예제에서는 print와 log 함수)
예제에서 정의된 다른 선언은 모듈 내부에 한정된다(즉, 로컬 선언이 된다)..

  1. 한모한자(한 모듈에서 한개의 자바스크립트) 예제
    export default 사용
const study = new Student("EZ", 7, ["react", "javascript"]);

export default study;

오직 하나의 이름만 노출하는 모듈에서 사용한다.

모듈은 import 명령을 사용해 다른 자바스크립틑 파일을 불러와 사용할 수 있다.
외부에 여러 이름을 노출한 모듈을 import할 때는 객체구조분해를 활용할 수 있따.
export default를 사용해 한 이름만 노출한 경우에는 노출된 대상을 구조분해없이 한 이름으로 부를 수 있다.

import {print, log} from './js파일 이름'
import study from './js파일 이름'

print('메시지를 print');
log('메시지를 log');

study.print();

모듈에서 가져온 대상에 다른 이름을 부여할 수도 있다.

import {print as p, log as l} from './js파일 이름'

p('메시지를 print');
l('메시지를 log');

import *를 사용하면 다른 모듈에서 가져온 모든 이름을 사용자가 정한 로컬 이름 공간 안에 가둘 수 있다.

import * as fns from './js파일 이름'

커먼JS

커먼JS는 모든 버전의 노드에서 지원하는 일반적인 모듈 패턴이다.
바벨이나 웹팩에서 사용할 수 있다.
커먼JS를 사용하면 자바 객체를 module.exports를 사용해 아래 예제처럼 export할 수 있다.

const print(message) => log(message, new Date())

const log(message, timestamp) => console.log(`${timestamp.toString()}: ${message}`);

module.exports = {print, log}

커먼 JS는 import문을 지원하지 않는다.
대신 require 함수로 모듈을 import할 수 있다.

const { print, log } = require('./js파일 이름')