티스토리 뷰
Class
ES6에서 class 라는 문법이 추가 되었고, 기존의 prototype 기반으로 클래스를 만드는 것보다 명료하게 클래스를 만들 수 있게 되었습니다.
1. 클래스 정의
ES6에서 클래스는 특별한 함수입니다. 그렇기 때문에, 함수와 동일하게 클래스 선언(Class declarations)과 클래스 표현(Class expressions)으로 클래스를 만들 수 있습니다 ([자바스크립트] 함수(Function), 즉시실행함수(Immediately-invoked function expression) 참고)
클래스 선언(Class declarations)
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
클래스 선언은 함수 선언과 달리 호이스팅 되지 않습니다. ([자바스크립트] 유효범위(Scope)와 호이스팅(Hoisting) 참고)
var p = new Polygon(); // ReferenceError
class Polygon {}
클래스 선언은 호이스팅 되지 않습니다.
클래스 표현(Class expressions)
익명 클래스와 기명 클래스를 만들 수 있습니다.
// unnamed
var Polygon = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
// named
var Polygon = class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
};
클래스 표현(Class expressions) 또한 클래스 선언(Class declarations)와 같이 호이스팅(hoisting)이 되지 않습니다.
2. 메소드 정의
ES6의 class에서, 클래스의 몸통(body)는 {} 이며, class 메소드는 class의 {} 안에 정의해야 합니다.
Strict mode
클래스 몸통(body)는 strict mode로 실행됩니다. ([자바스크립트] 엄격 모드(strict mode) 참고)
생성자(Constructor)
생성자 메소드는 객체의 생성과 초기화를 하는 특별한 메소드입니다. 클래스에서 constructor 이름을 갖는 메소드는 하나여야 합니다.
var Polygon = class {
constructor(height, width) {
this.height = height;
this.width = width;
}
constructor(height2, width2) {
this.height = height2 * 2 ;
this.width = width2 * 2;
}
};
constructor는 하나여야 합니다.
생성자 메소드에서 super 키워드를 통해 상위 클래스의 생성자 메소드를 호출 할 수 있습니다.
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
class Square extends Polygon {
constructor(length) {
// length로 다각형의 넓이와 높이를 정의하기 위해 부모클래스의 생성자를 호출합니다.
super(length, length);
// Note: 파생 클래스에서, 'this'를 사용하기 전에는 반드시 super()를
// 호출하여야 합니다. 그렇지 않을 경우 참조에러가 발생합니다.
this.name = 'Square';
}
get area() {
return this.height * this.width;
}
set area(value) {
this.area = value;
}
}
var test = new Square(4);
console.log(test.area);
생성자 메소드에서 this를 사용하기 위해서 super 메소드를 먼저 호출해야 합니다.
set, get 함수의 선언법은 [자바스크립트] getter, setter 참고바랍니다.
프로토타입 메소드(Prototype methods)
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
get area() {
return this.calcArea();
}
calcArea() {
return this.height * this.width;
}
}
const square = new Polygon(10, 10);
console.log(square.area);ES6는 메소드 정의를 위한 더 짧은 구문이 도입되었습니다. 다음 코드가 주어지면,
var obj = {
foo: function() {},
bar: function() {}
};ES6에서는 아래와 같이 줄일 수 있습니다.
var obj = {
foo() {},
bar() {}
};정적 메소드(static methods)
static 메소드는 클래스의 인스턴스 (var a = new testFunc()) 필요없이 호출 가능합니다. 또한 클래스의 인스턴스에서 static 메소드를 호출 할 수 없습니다.
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static distance(a, b) {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.sqrt(dx*dx + dy*dy);
}
}
const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
console.log(Point.distance(p1, p2));
var p3 = new Point(1, 1);
p3.distance(p1, p2);
class의 static 메소드
인스턴스 없이 정상적으로 distance가 호출 되는 것과, 인스턴스를 통해 distance를 호출 할 때 TypeError가 발생하는 것을 확인 할 수 있습니다.
오토박싱(Autoboxing)
autoboxing이란?
일반 함수에서 this는 window 객체를 가르키게 됩니다. this가 window 객체 (global object)를 가르키는 이유는 autoboxing 덕분입니다.
non-strict 모드에서 ([자바스크립트] this의 정체 참고) this 값이 null 혹은 undefined 일 경우 window 객체(global object)로 자동으로 변환해 주는 것을 autoboxing이라고 합니다.
프로토타입 기반의 클래스에서 autoboxing
프로토타입 기반의 class의 경우
function Animal() { }
Animal.prototype.speak = function(){
console.log(this);
return this;
}
Animal.eat = function() {
console.log(this);
return this;
}
let obj = new Animal();
let speak = obj.speak;
speak(); // global object
let eat = Animal.eat;
eat(); // global object
프로토타입 기반의 클래스의 autoboxing
autoboxing이 되어, 일반 함수를 호출하는 것처럼 메소드를 호출 한 경우 window 객체(global object)를 출력하는 것을 확인 할 수 있습니다.
ES6의 클래스 기반의 autoboxing
ES6의 class에서는 autoboxing이 되지 않습니다.
class Animal {
speak() {
console.log(this);
return this;
}
static eat() {
console.log(this);
return this;
}
}
let obj = new Animal();
let speak = obj.speak;
speak(); // undefined
obj.speak();
let eat = Animal.eat;
eat(); // undefined
Animal.eat();
ES6의 class는 autoboxing이 안됨
autoboxing이 되지 않아, 일반 함수를 호출하는 것처럼 메소드를 호출 한 경우 undefined가 출력되는 것을 확인 할 수 있습니다.
그렇기 때문에 ES6의 클래스에서 메소드를 변수에 저장하여 사용할 경우, this에 유의해서 사용해야 합니다.
3. 클래스 상속(sub classing)
ES6의 클래스 상속
extends 키워드를 통하여 클래스를 상속 받아, 자식 클래스를 만들 수 있습니다.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
speak() {
console.log(this.name + ' barks.');
}
}
var d = new Dog('Mitzie');
d.speak();
ES6의 클래스 상속
프로토타입 기반의 클래스 상속
프로토타입 기반의 클래스도 extends 키워드를 통해 상속 할 수 있습니다.
function Animal (name) {
this.name = name;
}
Animal.prototype.speak = function () {
console.log(this.name + ' makes a noise.');
}
class Dog extends Animal {
speak() {
console.log(this.name + ' barks.');
}
}
var d = new Dog('Mitzie');
d.speak();
프로토타입 기반의 클래스 상속
일반 객체의 클래스 상속
일반 객체는 extends 키워드를 통해 상속할 수 없습니다. 상속하고 싶다면 Object.setPrototypeOf 메소드를 사용하여 상속해야 합니다.
var Animal = {
speak() {
console.log(this.name + ' makes a noise.');
}
};
class Dog {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' barks.');
}
}
Object.setPrototypeOf(Dog.prototype, Animal);
var d = new Dog('Mitzie');
d.speak();
일반 객체의 클래스 상속
4. Species
class MyArray extends Array {
// 부모 Array 생성자로 종류 덮어쓰기
static get [Symbol.species]() { return Array; }
}
var a = new MyArray(1,2,3);
var mapped = a.map(x => x * x);
console.log(mapped instanceof MyArray); // false
console.log(mapped instanceof Array); // true
Symbol.species
Array를 상속받은 MyArray에서 Array의 default 생성자를 덮어 쓰고 싶을 경우, Symbol.species를 사용하면 됩니다. (get []의 문법은 [자바스크립트] getter, setter 참고 바랍니다.)
Symbol.species로 Array의 생성자를 가져오고, get [] 로 Array를 리턴함으로 부모 Array의 생성자를 덮어 쓸 수 있습니다.
5. super로 부모 클래스 호출하기
super 키워드를 홈하여 부모 클래스의 메소드를 호출 할 수 있습니다.
프로토타입 기반의 부모 클래스 메소드 호출
function Cat(name) {
this.name = name;
}
Cat.prototype.speak = function () {
console.log(this.name + ' makes a noise.');
};
function Lion(name) {
// `super()` 호출
Cat.call(this, name);
}
// `Cat` 클래스 상속
Lion.prototype = new Cat();
Lion.prototype.constructor = Lion;
// `speak()` 메서드 오버라이드
Lion.prototype.speak = function () {
Cat.prototype.speak.call(this);
console.log(this.name + ' roars.');
};
var lion = new Lion("BIG");
lion.speak();
프로토타입 기반의 부모 클래스 메소드 호출
프로토타입 기반의 클래스에서 부모 클래스의 메소드를 호출하기 위해서 call과 같은 함수를 사용해야 합니다. ([자바스크립트] API - call, apply 함수 참고)
ES6 클래스 기반의 부모 클래스 메소드 호출
class Cat {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise.');
}
}
class Lion extends Cat {
speak() {
super.speak();
console.log(this.name + ' roars.');
}
}
var lion = new Lion("BIG");
lion.speak();
ES6 클래스 기반의 부모 클래스 메소드 호출
ES6 클래스는 super 메소드를 사용하여 부모 클래스의 메소드를 호출 할 수 있습니다.
'JavaScript' 카테고리의 다른 글
| [자바스크립트] ES6(ECMA Script 6) - 기본 매개변수(Default parameter) (1) | 2017.01.17 |
|---|---|
| [자바스크립트] ES6(ECMA Script 6) - 나머지 매개변수(Rest parameter) (1) | 2017.01.16 |
| [자바스크립트] getter, setter (6) | 2017.01.13 |
| [자바스크립트] 엄격 모드(strict mode) (6) | 2017.01.10 |
| [자바스크립트] ES6(ECMA Script 6) - let, const (0) | 2017.01.04 |
