안녕하세요. 이번 시간에는 stage-3에 이어 stage-2에 대해 알아보겠습니다! 1~3년 내에 정식 스펙에 들어갈 만한 친구들입니다.
아직 브라우저에서 지원하는 것이 없습니다. @babel/preset-stage-2를 설치하면 이 기능들을 사용할 수 있습니다. class decorators, static class는 정말 놀라운 변화입니다.
다음 코드는 브라우저에서 동작하지 않으니 따라 치지는 마시고 눈으로만 보세요.
static class fields
stage-3에 private와 class properties 스펙이 존재하고 stage-2에는 스태틱 필드에 대한 스펙이 존재합니다. ES2015에서는 스태틱 메서드만 지원했다면 이제는 그냥 프로퍼티도 앞에 static을 붙여 스태틱 프로퍼티로 만들 수 있습니다. 자바의 static과 비슷하게 기능합니다. new를 붙여 인스턴스화하지 않아도 접근 가능해집니다.
class ZeroCho {
static name = 'zero';
year = 1994;
static getYear() {
return this.year;
}
}
ZeroCho.name; // 'zero'
ZeroCho.getYear(); // 1994
예제에서 static name이 이번 주제입니다. static getYear은 ES2015에 이미 들어간 스펙이고요. 메서드가 아닌 단순 프로퍼티도 스태틱화 할 수 있게 되었습니다.
static 필드가 잘 이해되지 않는 분들을 위해 설명 드리자면, new를 붙여 인스턴스로 만들지 않아도 클래스의 속성에 접근 가능한 필드입니다. 예를 들면, Array.isArray
나 Object.keys
같은 메서드들이 있습니다. new Array()
, new Object()
로 인스턴스화해서 메서드를 호출하는 게 아니라 클래스 그 자체에 들어있는 메서드들이 static 필드입니다. 리액트에서는 propTypes나 defaultProps같은 것들이 static 프로퍼티입니다.
class decorators
리액트를 하셨던 분이라면 몇 번 보셨을텐데요. 클래스를 감싸는 함수를 만드는 방법입니다. HOC를 만들 때 가끔 이런 문법을 쓰는 것을 보신 적이 있을 겁니다.
function hello(msg) {
return function(target) {
target.hello = msg;
};
}
function readonly(target, key, descriptor) {
descriptor.writable = false;
return descriptor;
}
@hello('안녕')
class ZeroCho {
@readonly
static name = 'zerocho';
}
ZeroCho.hello; // '안녕'
ZeroCho.name; // 'zerocho';
ZeroCho.name = 'babo'; // Error 발생
클래스와 속성 앞에 @로 시작하는 함수가 붙었죠? 이것들이 decorator입니다. 다음 줄에 나오는 클래스나 속성이 target으로 들어가고요. hello 함수를 보면 '안녕'이라는 글자를 받아서 target.hello에 그 글자를 대입합니다. 여기서의 target은 @hello 다음에 나오는 ZeroCho 클래스입니다.
readonly 함수를 보면 다음에 나오는 속성의 descriptor를 받아 writable을 false로 만들어주었습니다. 따라서 @readonly decorator 다음에 나오는 name 속성은 수정할 수 없습니다. 여기서의 target은 name 속성이 됩니다. descriptor은 name 속성의 descriptor인 것이고요.
throw expressions
throw를 자유자재로 할 수 있습니다. 신나게 에러를 뱉어봅시다. 함수의 인자를 검사하거나 할 때 유용하게 쓸 수 있습니다.
a = a || throw 'a는 필수 인자입니다';
b = b && throw 'b는 거짓(falsy) 값이어야 합니다.'
function(c = throw 'c는 필수 인자입니다') { }
d = () => throw '무조건 에러'
e = e ? true : throw 'e는 참(truthy) 값이어야 합니다.'
물론 throw의 인자는 catch의 error로 전달됩니다.
Symbol.prototype.description
심볼을 만들 때 어떤 키워드로 만들었는지 확인하는 기능입니다.
Symbol('zerocho').description === 'zerocho'
자바스크립트의 class에 점점 기능이 붙기 시작하네요. 다른 객체 지향 언어의 class 기능들이 거의 다 들어온 것 같습니다. 다음 시간에는 stage-1에 대해서 알아보겠습니다!