본문 바로가기

자바스크립트

ES6의 주요 특징 정리



let과 const


전통적으로 자바스크립트는 함수스코프와 전역스코프만을 지원하여 변수의 생명주기 및 접근을 제어해왔다. 하지만 ES6에서부터는 블록스코프도 지원하게 되었다. 이를 가능하게 해주는 것이 let과 const이다.

아래의 코드는 블록 스코프를 따르는 여타 언어에서는 에러를 발생시켰을 것이다. 하지만 함수스코프와 전역스코프를 따르는 자바스크립트에서는 문제없이 작동한다. 그러나 이는 많은 에러와 버그의 원인이었으며, let과 const가 도입된 이유이다.


1
2
3
4
5
6
if (false) {
  var x = 'hello';
}
 
console.log(x); // undefined
 
cs


이번엔 let을 사용해보자.


1
2
3
4
5
6
if (false) {
  let x = 'hello';
}
 
console.log(x); // ReferenceError: x is not defined
 
cs


let을 사용하면 선언한 변수는 블록안에서만 유효하게 된다. 따라서 블록 밖에서 접근했더니 ReferenceError를 발생시켰다.

const역시 마찬가지로 블록스코프를 따른다. const와 let의 차이점은 const는 상수로 값을 할당한다는 점이다. 따라서 값을 변경시키려고하면 에러를 발생시킨다.


1
2
3
const x = 'Hello World';
= 'Show me the money'// Uncaught TypeError: Assignment to constant variable.
 
cs


하지만 이는 정확한 표현이 아니다. const와 바인딩 된 값은 상수가되지만 할당된 값은 변경이 가능하다. 따라서 아래와 같은 코드도 정상적으로 동작한다.


1
2
3
4
5
const x = {};
// x = null; 에러
x.a = 'Apple';
x.b = 'Banana';
 
cs



화살표 함수 (Arrow Function)


ES6에서 소개된 가장 인상적인 기능중의 하나는 화살표 함수의 지원이다. 화살표 함수는 함수 정의를 보다 간결한 구문으로 콜백을 정의할 때 특히 유용하다. 아래는 고전적인 필터링의 예시이다.


1
2
3
4
5
const numbers = [123456789];
const even = numbers.filter(function (x) {
    return x % 2 === 0;
})
 
cs


다음은 화살표 함수로 작성한 동일한 코드이다.


1
2
const numbers = [123456789];
const even = numbers.filter(x => x % 2 === 0);
cs


function 키워드가 사라지고 함수의 인자 다음에 =>가 나오고 본문을 작성한다. 본문이 return 문 하나만 있을 경우 { }는 생략이 가능하다. 또한 함수의 인자가 하나일 경우 ( ) 역시 생략 가능하다.


화살표 함수의 중요한 기능중 하나는 어휘 범위(Lexical Scope)로 바인딩된다는 것이다. 즉, 화살표 함수 내부의 this값은 부모 블록의 this값과 같다.

아래의 예시는 this값의 범위가 달라 원하는 대로 동작하지 않는 경우이다. 일반적으로 function 키워드는 각각이 새로운 this값을 생성하기 때문이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
function DelayedGreeter (name) {
  this.name = name;
}
 
DelayedGreeter.prototype.greet = function () {
  setTimeout(function cb () {
    console.log('Hello ' + this.name);
  }, 1000);
}
 
const greeter = new DelayedGreeter('World');
greeter.greet();  // Hello undefined
 
cs


그리고 위의 코드가 원하는대로 동작하게 하기 위해선 bind를 사용해 this값을 바인딩해주어야 했다.


1
2
3
setTimeout((function cb () {
    console.log('Hello ' + this.name);
  }).bind(this), 1000);
cs


그러나 화살표함수는 부모 블록의 this와 바인딩이 자동으로 이루어지기 때문에 훨씬 간결하게 문제를 해결할 수 있다.


1
setTimeout(() => console.log('Hello ' + this.name) , 1000);
cs



클래스 구문


ES6에서 클래스 구문이 도입되었다. 하지만 자바스크립트 런타임에 의해 내부적으로 객체가 관리되는 방식이 바뀐 것은 아니어서 여전히 프로토타입을 통해 속성과 함수를 상속한다는 점이 중요하다. 클래스 구문의 도입은 개발자에게 유용하고 뛰어난 가독성을 제공하며, 단지 편의를 위한 것이다. 아래는 전통적인 프로토타입 기반의 Person 함수를 보여준다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Person (name, age, job) {
  this.name = name;
  this.age = age;
  this.job = job;
}
 
Person.prototype.getAgeAndName = function () {
  return this.age + ' ' + this.name;
}
 
Person.older = function (person1, person2) {
  return person1.age >= person2.age ? person1 : person2;
}
 
const seo = new Person('SDS'30'Programmer');
const ahn = new Person('AHY'28'Staff');
 
console.log(seo.getAgeAndName());
console.log(Person.older(seo, ahn));
 
cs


다음은 클래스 구문을 통해 작성한 동일한 코드이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Person {
  constructor (name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
  }
 
  getAgeAndName () {
    return this.age + ' ' + this.name;
  }
 
  static older (person1, person2) {
    return person1.age >= person2.age ? person1 : person2;
  }
}
 
const seo = new Person('SDS'30'Programmer');
const ahn = new Person('AHY'28'Staff');
 
console.log(seo.getAgeAndName());
console.log(Person.older(seo, ahn));
 
cs


클래스 구문을 통해 표현하면 훨씬 이해하기 쉽고 간결하다. 생성자를 명시적으로 기술하고 있고, static 메서드를 선언할 수도 있다.

클래스 구문의 유용한점은 extends 키워드와 super 키워드를 통해 Person 프로토타입을 확장할 수 있다는 것이다. 아래와 같이 확장 가능하다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
class PersonWithCar extends Person{
  constructor (name, age, job, car) {
    super(name, age, job);
    this.car = car;
  }
 
  getAgeAndName () {
    return this.age + ' ' + this.name + ' ' + this.car;
  }
}
 
const kwon = new PersonWithCar('KMS'30'Technician''K5');
 
console.log(kwon.getAgeAndName ());
cs


여기서 주목해야 할 점은 다른 객체지향언어에서 일반적으로 나타나는 모습과 유사하다는 점이다. 확장하고자 하는 클래스로부터 새로운 클래스를 선언하고, super 키워드를 사용하여 부모 생성자를 호출하는 새로운 생성자를 정의하였으며, 기존의 메서드를 오버라이딩했다.



향상된 객체 리터럴


1. 속성과 할당하고자 하는 값이 일치하는 경우 생략 가능하다. 


1
2
3
4
5
6
const a = 'Apple';
const b = 'Banana';
 
const es5 = { a: a, b: b };
const es6 = { a, b};
 
cs


2. 함수를 속성으로 가지는 경우 function 키워드는 생략 가능하다.


1
2
3
4
5
6
7
8
9
10
11
12
13
const es5 = {
  age: 30,
  getAge: function () {
    return this.age;
  }
}
const es6 = {
  age: 30,
  getAge () {
    return this.age;
  }
}
 
cs


3. 객체의 속성을 동적으로 할당할 수 있다.


1
2
3
4
5
6
const name = 'SDS';
const person = {
  [name + "'s Age"]: 30
}
console.log(person) // { "SDS's Age": 30 }
 
cs


4. 새로운 getter, setter 구문이 추가되었다.

참고로 set함수는 get함수가 반환하는 값을 반환하도록 되어있다. (17번째 줄)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const person = {
  name'George',
  surname: 'Boole',
 
  get fullname () {
    return this.name + ' ' + this.surname;
  },
 
  set fullname (fullname) {
    let parts = fullname.split(' ');
    this.name = parts[0];
    this.surname = parts[1];
  }
}
 
console.log(person.fullname); // George Boole
console.log(person.fullname = 'Alan Turing'); // Alan Turing
console.log(person.name); // Alan
 
cs



Template 표기법


간단하다. 빽틱(키보드 Tab키 위에 1 왼쪽에 위치)으로 둘러싸고 원하는 문자열을 입력하면 된다. ${ }안에 넣고 싶은 변수를 넣으면 알아서 해당 위치에 매핑된다.


1
2
3
4
const hello = 'Hello';
const to = 'Everybody!';
 
console.log(`${hello} ${to}`);
cs



비구조화 할당 (또는 구조 분해 할당)


배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 표현식이다.


배열 구조 분해


1
2
3
4
5
6
let foo = ["one""two""three"];
 
let [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"
cs


객체 구조 분해


1
2
3
4
5
6
7
let fruit = {
    a: 'Apple',
    b: 'Banana',
}
let { a, b } = fruit;
console.log(a);    // 'Apple'
console.log(b);    // 'Banana'
cs






























'자바스크립트' 카테고리의 다른 글

자바스크립트 apply, call, bind  (0) 2019.03.12
스코프와 호이스팅  (0) 2019.03.08