ECMAScript2015
by jbee
[ES6] 6. Class sugar syntax
ES6에서자바스크립트에는존재하지않았던클래스(Class)가 도입되었다. 자
바스크립트에대해잘모르는사람들이Java에서의클래스와똑같은기능을
하는녀석인줄알고 많이혼동한다. 자바스크립트는기본적으로프로토타입
기반의언어이기 때문에새로도입된이클래스도프로토타입기반이다. 객체
지향을흉내내고 있지만, 그 내부는여전히프로토타입으로구성되어있는것
이다. 프로토타입기반으로객체지향적으로설계하는것이복잡하여클래스라
는 sugar syntax 문법이도입된것이다. 그렇기 때문에이에따른제약사
항이많다. 편한만큼고려해야할사항도많은것이다. 하나씩살펴보자.
클래스는선언문또는표현식으로선언할수있다.
//클래스 선언문으로 클래스 선언
class name {
//...
}
//클래스 표현식으로 클래스 선언
let name = class {
//...
}
let name = class inner_name {
//...
}
console.log(typeof name); //function
자바스크립트엔진은 class 키워드를만나면 Class 오브젝트 를생성한다.
 Class 오브젝트 도마찬가지로 String ,  Function 과 같은하나의오브젝
트타입이다.
cf> 표현식으로 선언했을 때의 inner‑name은 클래스 내부에서 자신을 호
출할 때 사용한다.
Class keyword 특징
클래스의선언부는 let 과  const 와마찬가지로호이스팅은되지만
 temporary dead zone 이형성된다.
//Not hoisting
let foo = new Foo();
class Foo {
}
//Error:Use before declaration
클래스를선언한다음,  new 키워드를통해인스턴스를생성할수있다.
Class syntax 특징
1. 클래스의코드는‘use strict’를선언하지않아도strict 모드에서실행된
다.
2. 메서드를작성할때, function 키워드와콜론( : )을작성하지않는다.
3. 메서드사이에콤마(,)를작성하지않는다.
4. 생성자함수를통해인스턴스를생성하면window에설정되지만class
키워드를통해생성하면window에설정되지않는다.
//class method
class Student {
getName() {
console.log("name");
}
getScore() {
console.log("score");
}
}
let student = new Student();
student.getName(); //name
student.getScore(); //score
바로메소드를정의하고, 콤마(,)가 없다.
생성자함수를통해인스턴스를생성하면window에설정되지만class 키워
드를통해생성하면window에설정되지않는다.
class Student {
//...
}
function Foo() {
//...
}
console.log(window.Foo); // function Foo() {...}
console.log(window.Student); //undefined
Sugar Syntax
 Class keyword는 sugar syntax 라고 했다. 자바스크립트는기본적으
로 prototype 기반의언어이기 때문에엔진이 prototype 에메서드들을
연결한다. 즉, 클래스에서메서드를추가하면자동으로 prototype 에추가
되는것이다. 자바스크립트에서는프로토타입을사용해서클래스밖에서도메
서드를추가할수있다. 이미생성된인스턴스에메서드를추가하게 되면, 이전
에생성되었던인스턴스들이새로추가된메서드들을공유해야하기 때문에부
하가 걸리지만코드가 유연해진다는장점도존재한다. 위예제코드에서생성한
 Student 클래스의프로토타입에새로운메서드를추가하고 이전에생성되
었던인스턴스에서새롭게 추가한메서드를호출할수있는것이다.
ES5 code
//add method to prototype
Student.prototype.newMethod = function() {
console.log("Add new Method");
}
student.newMethod(); //Add new Method
 new 연산자는생성자를호출하면서받은인자들을 constructor 의파라
미터로전달한다.
//new keyword
class Student {
constructor(name, score) {
this._name = name;
this._score = score;
}
getName() {
return this._name;
}
}
let s = new Student("Jbee", 100);
console.log(s.name); //Jbee
console.log(s._score); //100
console.log(s.getName()); //Jbee
 new keyword
위예제코드에서볼수있듯이 class 키워드로선언한클래스에대해서
 new keyword를통해인스턴스를생성할수있다. 이때클래스내부에별도
의 constructor 가 설정되어있지않으면기존의 protytype 의
constructor가 호출되고 이를 default constructor 라고 부른다. 별도로
작성된 constructor 는 Student.prototype.constructor 로호출된
다.
new 키워드가 실행되는메커니즘은다음과 같다.
1. constructor는우선적으로빈(empty) 오브젝트(인스턴스)를생성한다.
2. 넘겨받은파라미터를생성한빈오브젝트의프로퍼티에설정한다.
3. 인스턴스를먼저생성하므로, constructor 내부에서는this keyword를
통해인스턴스자신을가리킬수있다.
4. constructor에별도의return이설정되어있지않으면new를실행한곳
으로해당클래스의인스턴스를반환한다.
cf) constructor는 별도의 return을 설정할 수 있다. 하지만 Number,
String 값이 return value로 지정되어 있으면 이를 무시하고 인스턴스 자신
을 return 한다.
 extends keyword
자바스크립트에서도 extends 라는키워드를통해클래스간의상속이가능
해졌다. 상속받은클래스(이하슈퍼클래스)의메소드를사용할수있다.
class Foo {
getName() {
console.log("Foo");
}
}
class Bar extends Foo {
}
let bar = new Bar();
bar.getName(); //Foo
슈퍼클래스의메소드를오버라이딩(Overriding) 할수있다.
class Foo {
getName() {
console.log("Foo");
}
}
class Bar extends Foo {
// override
getName() {
console.log("Bar");
}
}
let bar = new Bar();
bar.getName(); //Bar
 super 키워드를통해슈퍼클래스의메소드에접근할수있다.
class Foo {
getName() {
return "Foo";
}
}
class Bar extends Foo {
getName() {
return super.getName() + " Bar";
}
}
let bar = new Bar();
bar.getName(); //Foo Bar
constructor keyword
서브클래스에서정의된 constructor 가 없다면슈퍼클래스의
 constructor 가 호출된다.
class Foo {
constructor() {
console.log("Foo constructor");
}
}
class Bar extends Foo {
}
let bar = new Bar();
//console> Foo constructor
서브클래스에서 constructor 를정의하려면반드시constructor 내부에
서 super() 를호출해야한다.
Bad code
class Foo {
constructor() {
console.log("Foo");
}
}
class Bar extends Foo {
constructor() {
console.log("Bar");
}
}
let bar = new Bar();
//ReferenceError: this is not defined
 constructor() 메소드안에서 super() 를호출해주면, 슈퍼클래스가 생
성되고 서브클래스가 생성된다.
class Foo {
constructor() {
console.log("Foo constructor");
}
}
class Bar extends Foo {
constructor() {
super();
console.log("Bar constructor");
}
}
let bar = new Bar();
//console> Foo constructor
//console> Bar constructor
static keyword
자바스크립트클래스에서 static 키워드를사용하면정적메소드를정의할
수있다. 정적메소드라함은인스턴스를생성하지않고 사용할수있는메소드
를말한다. 정적메소드는인스턴스를생성하지않고도호출할수있지만인스
턴스에서는호출할수없다.
class Foo {
static getName() {
console.log("Foo");
}
}
Foo.getName(); //Foo
let foo = new Foo();
foo.getName();//not a function
정적메소드는 prototype 에추가되지않는다.
class Foo {
static getName() {
console.log("Foo");
}
getAlias() {
console.log("foo");
}
}
console.log(Foo.prototype.getName === Foo.getName);//false
console.log(Foo.prototype.getAlias === new Foo().getAlias);
클래스내부에서 정적 변수(static variable) 를지정할수는없지만클래
스밖에서지정할수있다.
class Foo {
//...
}
Foo.name = "foo";
타입스크립트에서는가능합니다.
new.target
 new.target 을이용하면슈퍼클래스에서서브클래스의static method에
접근할수있다.
class Foo {
constructor() {
console.log(new.target);//[Function: Bar]
console.log(typeof new.target);//function
console.log("Foo: ", new.target.getName());//Foo: bar
}
}
class Bar extends Foo {
constructor() {
super();
}
static getName() {
return "bar";
}
}
let bar = new Bar();
ES6에서추가된sugar syntax class에대해정리해봤다. TypeScript에서는
보다더객체지향적인클래스로서사용할수있다. 아직불완전한ES6의클래
스는신경써야할부분도많지만제대로이해하면 prototype 을사용하는것
보다효율적으로자바스크립트코드를작성할수있을것이다.
6. end

[ES6] 6. Class