React를 위한 ES6

let

기존 ES5에서는 var 키워드를 사용하여 변수를 선언하는 유일한 방법이었다. 자바스크립트는 {} 중괄호를 사용하여 코드 블록을 만들고 변수의 영역은 그 블록 안으로 한정된다. 그러나, var 키워드를 사용하면 if/elsefor 구문등을 사용하여 코드 블록을 만들어도 변수의 영역이 제한되지 않는 경우가 있다. 이러한 혼란으로 인해 변수 영역을 코드 블록 안으로 한정시킬수 있는 let이 추가되었다.
앞으로는 ES6를 지원하는 개발환경에서 값의 재할당이 필요한 변수를 선언하는 경우 let을 사용하여야 한다.

var topic = "자바스크립트";

if (topic) {
  var topic = "리액트";
  console.log('블록', topic); // 블록 리액트
}

console.log('글로벌', topic); // 글로벌 리액트

const

const는 값을 변경할 수 없는 변수로 값을 재할당 할 필요가 없는 경우 사용한다.

const pizza = true;
pizza = false;
// Uncaught TypeError: Assignment to constant variable.

템플릿 리터럴 (Template Literals)

역 따옴표(backticks)을 사용하여 문자열을 연결하거나 문자열 중간에 변수를 삽입하여 사용할 수 있다.
또한 ${}에는 값을 만들어내는 자바스크립트 식이라면 어떤 것이든 들어갈 수 있다.

// ES5
var student = {
 name: 'John Kagga',
 city: 'Kampala'
};

var message = 'Hello ' + student.name + ' from ' + student.city;
console.log(message); // Hello John Kagga from Kampala

// ES6
let message = `Hello ${student.name} from ${student.city}`;
console.log(message); // Hello John Kagga from Kampala

디폴트 파라미터 (Default Parameter)

함수 호출시에 값을 지정하지 않으면 디폴트 값을 사용할 수 있다.

function greet(name = 'Fellow', greeting = 'Welcome') {
 return `${greeting} ${name}`;
}

console.log(greet()); // Welcome Fellow
console.log(greet('Elise')); // Welcome Elise
console.log(greet('Mike', 'Hi')); // Hi Mike

화살표 함수 (Arrow Function)

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

// ES5
function (name) { 
  return name.toUpperCase();
}

// ES6 arrow function
name => name.toUpperCase();

// zero parameters
const hello = () => console.log('Hello React!');

// two parameters
const location = (name, city) => console.log(`${name} is from ${city}.`);
  • 구문이 짧다
  • 읽고 쓰기가 쉽다
  • 한줄 코드인경우 return 구문없이 자동으로 반환된다

화살표 함수와 this

class App extends React.Component {
  handleClick() {
    console.log(this);
  }
  render() {
    return (
      <button type="button" onClick={this.handleClick.bind(this)}>
        Goodbye bind
      </button>
    );
  }
}

예제

  • bind()함수는 전달된 인자를 this로 보내는 바인딩 함수를 만든다.
  • this는 다른 언어와 달리 실행 문맥(context)에 따라 변한다.
  • 화살표 함수의 this는 외부함수(부모함수)의 this를 상속받기 때문에 this는 항상 일정하다.
  • React에서 이벤트 핸들러 함수를 바인드할때 화살표 함수를 사용한다.

리액트에서 화살표 함수(arrow function)는 선택이 아닌 필수

구조분해 (Destructuring) / 구조화 할당 (Destructuring Assignment)

구조 분해를 사용해 객체 안에 있는 필드 값을 원하는 변수에 대입할 수 있다.

  • 배열 구조 분해
    ```js
    // ES5
    const points = [20, 30, 40];
    const x = points[0];
    const y = points[1];
    const z = points[2];
    console.log(x, y, z); // 20 30 40

// ES6
const points = [20, 30, 40];
const [x, y, z] = points;
console.log(x, y, z); // 20 30 40

// y 값 무시하기
const [x, , z] = points
console.log(x, z); // 20 40


- 객체 구조 분해
```js
// ES5 
const car = {
 type: 'Toyota',
 color: 'Silver',
 model: 2007
};

const type = car.type;
const color = car.color;
const model = car.model;

console.log(type, color, model); // Toyota Silver 2007

// ES6
const {type, color, model} = car;
console.log(type, color, model); // // Toyota Silver 2007

개선된 객체 리터럴 (Enhanced Object Literal)

개선된 객체 리터럴은 구조를 다시 만들어내는 과정 또는 내용을 한데 묶는 과정이라 할 수 있다.

  • 객체 구조화
    ``js const type = 'Toyota' const color = 'Silver' const print = function() { console.log(${this.type}의 ${this.color}는 2007년식 모델이다`);
    }

let myCar = {type, color, print};
myCar.print();


- 변경된 객체 선언 문법
```js
// ES5
var skier = {
  name: name,
  sound: sound,
  powderYell: function() {
    var yell = this.sound.toUpperCase();
    console.log(yell + yell + yell + '!!!');
  }
  speed: function(mph) {
    this.speed = mph;
    console.log('속력(mph):', mph);
  }
}

// ES6
let skier = {
  name,
  sound,
  powderYell() {
    let yell = this.sound.toUpperCase();
    console.log(`${yell} ${yell} ${yell}!!!`);
  }
  speed(mph) {
    this.speed = mph;
    console.log('속력(mph):', mph);
  }
}

스프레드 연산자 (Spread Operator)

스프레드 연산자는 ... 세개의 점으로 이루어진 연산자로, 몇 가지 다른 역할을 담당한다.

  • 반복가능한 객체를 확장(열거)하기

    const cities = ["Kampala", "Nairobi", "Lagos"];
    console.log(...cities); // Kampala Nairobi Lagos
    
  • 여러 배열을 조합하기
    ```js
    const east = ["Uganda", "Kenya", "Tanzania"];
    const west = ["Nigeria", "Cameroon", "Ghana"];

const countries = [...east, ...west];
console.log(countries); // [ 'Uganda', 'Kenya', 'Tanzania', 'Nigeria', 'Cameroon', 'Ghana' ]


> [배열 조작하기](https://gitlab.com/genn/ReactJS/tree/master/react-data-control)

- 나머지(rest) 연산으로 사용하기
```js
let lakes = ["경포호", "화진포", "송지호", "청초호"];
let [first, ...rest] = lakes;
console.log(rest.join(", ")) // 화진포, 송지호, 청초호
  • 함수의 인자를 배열로 모우기
    ```js
    function multiply(multiplier, ...theArgs) {
    return theArgs.map((element) => multiplier * element);
    }

let arr = multiply(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]


## 프라미스 (Promise)
프라미스는 비동기적인 동작을 다루는 방법이다. 비동기 요청에 프라미스를 사용하면 여러가지 성공이나 실패 처리를 단순화 할 수 있다.

- 비동기 프라미스 만들기
```js
function myAsyncFunction(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = () => resolve(xhr.responseText);
    xhr.onerror = () => reject(xhr.statusText);
    xhr.send();
  });
}

myAsyncFunction('https://jsonplaceholder.typicode.com/todos/1').then(
  json => console.log(json),
  err => console.log(new Error('조회 실패'))
)

Fetch API

Fetch API를 이용하면 Request나 Resposne와 같은 HTTP의 파이프라인을 구성하는 요소를 조작하는것이 가능하다. 또한 fetch() 메서드를 이용하여 비동기 네트워크 통신을 알기쉽게 기술할 수 있다. fetch는 이전에 제공하던 XMLHttpRequest 대체제이다.

  • XHR 사용하여 비동기 요청하기
    ```js
    // Set up our HTTP request
    var xhr = new XMLHttpRequest();
    // Setup our listener to process compeleted requests
    xhr.onreadystatechange = function () {
    // Only run if the request is complete
    if (xhr.readyState !== 4) return;
    // Process our return data
    if (xhr.status >= 200 && xhr.status < 300) {
      // What do when the request is successful
      console.log(JSON.parse(xhr.responseText));
    
    }
    };

xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts');
xhr.send();


- fetch를 사용하여 비동기 요청하기
```js
fetch('https://jsonplaceholder.typicode.com/posts')
    .then(function (response) {
        return response.json();
    })
    .then(function (data) {
        console.log(data);
    });

XHR vs Fetch API

클래스 (Class)

이전 자바스크립트에는 공식적으로 클래스가 없어서 프로토타입을 사용해 구현하였지만, ES6에는 클래스 선언이 추가되었다.

// ES5 
function Vacation(destination, length) {
  this.destination = destination;
  this.length = length;
}

Vacation.prototype.print = function() {
  console.log(this.destination + "은(는) " + this.length + "일 걸립니다");
}

var trip = new Vacation("마우이", 7);
trip.print() // 마우이은(는) 7일 걸립니다.

// ES6 
class Vacation() {
  constructor(destination, length) {
    this.destination = destination;
    this.length = length;
  }

  print() {
    console.log(this.destination + "은(는) " + this.length + "일 걸립니다");
  }
}

const trip = new Vacation("칠레", 7);
trip.print() // 칠레은(는) 7일 걸립니다.
  • extends를 이용한 클래스 확장 (상속)
    ```js
    class Expedition extends Vacation {
    constructor(destination, length, gear) {
    super(destination, length);
    this.gear = gear;
    }

    print() {
    super.print();
    console.log(당신의 ${this.gear.join("와(과) 당신의 ")}를(을) 가져오십시오.);
    }
    }

const trip = new Expedition("한라산", 3, ["선글라스", "배낭", "카메라"]);
trip.print();
// 한라산은(는) 3일 걸립니다.
// 당신의 선글라스와(과) 당신의 배낭와(과) 당신의 카메라를(을) 가져오십시오.


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

```js
// Example.js
const a = 1;
const b = 2;
export { a };
export const c = 3;
export default b;

// Example2.js
import d, { a, c as e } from './Example';
console.log(a, d, e); // 1, 2, 3