Classes
ES5의 함수보다 ES6(i.e. ES2015)의 클래스를 사용하기
- 상속이 필요한 경우에는 ES6 클래스를 사용하는 것이 좋음
- 하지만 크고 복잡한 객체가 필요하지 않은 경우, 작은 함수를 쓰는 것이 낫다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80// bad
const Animal = function(age) {
if (!(this instanceof Animal)) {
throw new Error("Instantiate Animal with `new`");
}
this.age = age;
};
// 함수 설정
Animal.prototype.move = function move() {};
// good
class Animal {
constructor(age) {
this.age = age;
}
move() {
/* ... */
}
}
///////////////
// bad
const Mammal = function(age, furColor) {
if (!(this instanceof Mammal)) {
throw new Error("Instantiate Mammal with `new`");
}
// call 함수를 이용해 age 전달
Animal.call(this, age);
this.furColor = furColor;
};
Mammal.prototype = Object.create(Animal.prototype);
Mammal.prototype.constructor = Mammal;
// 함수 정의
Mammal.prototype.liveBirth = function liveBirth() {};
// good
class Mammal extends Animal {
constructor(age, furColor) {
// super() 을 이용해 상속
super(age);
this.furColor = furColor;
}
liveBirth() {
/* ... */
}
}
//////////////
// bad
const Human = function(age, furColor, languageSpoken) {
if (!(this instanceof Human)) {
throw new Error("Instantiate Human with `new`");
}
Mammal.call(this, age, furColor);
this.languageSpoken = languageSpoken;
};
Human.prototype = Object.create(Mammal.prototype);
Human.prototype.constructor = Human;
Human.prototype.speak = function speak() {};
// good
class Human extends Mammal {
constructor(age, furColor, languageSpoken) {
super(age, furColor);
this.languageSpoken = languageSpoken;
}
speak() {
/* ... */
}
}
Method Chaining 사용하기
Method Chaining 이란?
Named Parameter Idiom으로, OOP에서 여러 메소드를 이어서 호출하는 문법이다.
각각의 메소드는 객체 (
this
) 를 반환하며, 여러 메소드를 순차적으로 선언할 수 있다. 이를 통해 중간 결과값을 따로 변수에 저장하지 않아도 하나의 문장 만으로 메소드를 이어서 호출할 수 있다. 따라서 장기적으로는 유지, 보수에 도움이 된다.Named Parameter Idiom이란?
1
File f = OpenFile("foo.txt", true, false);
File 객체에 대한 설정을 생성자의 인자로써 넘기면 인자의 개수도 많아지고, 헷갈리기 쉽다. 이 때 Named Parameter Idiom 을 사용하면,
1
2
3File f = OpenFile("foo.txt")
.readonly()
.appendWhenWriting();위와 같이 method chaining을 사용하여 간결하게 표현할 수 있으며, parameter의 위치를 기억할 필요가 없으므로 실수를 방지할 수 있다.
- 객체 (
this
) 를 반환하여 연속적 (순차적) 으로 함수를 호출할 수 있음
- 객체 (
1 | class Car { |
상속보다는 조합을 사용하기
has-a
관계에서는 조합을 사용해야 함
c.f ) 조합보다 상속을 이용하면 좋은 경우
- 상속 관계가
has-a
가 아닌is-a
일 때- 상속; Human → Animal :
is-a
- 조합; User → UserDetails :
has-a
- 상속; Human → Animal :
- Base Class 의 코드를 재사용할 수 있을 때
Human
can move like allanimals
- Base Class를 수정 함으로써 이에 따른 클래스들을 전체적으로 변경하고 싶을 때
- Change the caloric expenditure of
all animals
when they move.
- Change the caloric expenditure of
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45// bad
class Employee {
constructor(name, email) {
this.name = name;
this.email = email;
}
// ...
}
// Bad because Employees "have" tax data.
// EmployeeTaxData "is not" a type of Employee.
class EmployeeTaxData extends Employee {
constructor(ssn, salary) {
super();
this.ssn = ssn;
this.salary = salary;
}
// ...
}
// good
// extending보다는 다른 클래스로 생성하고
class EmployeeTaxData {
constructor(ssn, salary) {
this.ssn = ssn;
this.salary = salary;
}
// ...
}
class Employee {
constructor(name, email) {
this.name = name;
this.email = email;
}
// Employee 클래스의 메소드를 통해 EmployeeTaxData 객체를 이용하여 this의 taxData 를 설정한다.
setTaxData(ssn, salary) {
this.taxData = new EmployeeTaxData(ssn, salary);
}
// ...
}