개발블로그
JS Class (2018.10.04) 본문
ES6부터 자바스크립트에도 클래스개념이 도입되었다고 한다.
C나 JAVA에서 봐왔던, 내가 알던 클래스와는 조금 다르기에 정리해 보려고 한다.
클래스를 사용해보자!
// define Person class
class Person {
constructor(name, age, email) {
this.name = name;
this.age = age;
this.emailList = email ? [email] : [];
}
introducMyself() {
return `I'm ${this.name}, ${this.age}years old.`;
}
// Getter Method
get getEmailList() {
return `Email : ${this.emailList.join(', ')}`;
}
// Setter Method
set addMyEmail(email) {
this.emailList.push(email)
}
}
// create new instance
const me = new Person('kevin', 30);
me.addMyEmail = 'myEmail@gmail.com';
console.log(me.introduceMyself()); // "I'm kevin, 30."
console.log(me.getEmailList); // Email : 'myEmail@gmail.com'
class 키워드를 이용하여 클래스 객체를 생성한다. 생성자는 꼭 constructor함수를 이용해야 하며 한 클래스 내에는 생성자가 여럿일 수 없다.
introduce처럼 일반적인 메소드를 정의할 수 있다.
메소드 앞에 get, set을 붙여 getter, setter함수를 만들 수 있는데, 이에 대해 알아보자.
Get 메소드
정의하는 방법은 그냥 메소드앞에 get키워드를 붙이기만 하면 된다.
사용하는 방법이 좀 특이한데, getEmailList라는 함수가 마치 멤버변수인 것처럼 me.getEmailList로 사용하면 된다.
그렇다면 me.getEmailList()로 사용해보면 어떻게 될까? 궁금해서 한번 해봤다.
// in console
me.getEmailList()-> VM47869:1 Uncaught TypeError: me.getEmailList is not a function
at <anonymous>:1:4
위와같이 타입에러가 뜬다. 음…. 클래스 인스턴스 me를 까보자!
// in console
me-> Person {name: "kevin", age: 30, emailList: Array(1)}
age: 30
emailList: ["myEmail@gmail.com"]
name: "kevin"
getEmailList: "Email : myEmail@gmail.com"
__proto__: Object
getEmailList가 ‘멤버변수인 것처럼’이 아니라 진짜 멤버변수로 등록되어있다…!
찾아보니,
‘The get syntax binds an object property to a function that will be called when that property is looked up.’.
오브젝트 프로퍼티를 그 프로퍼티에 접근할때 호출되는 함수로 바인딩한다.
말이 어렵다… 솔직히 잘 이해가 안된다…
‘해당 오브젝트의 프로퍼티에 get 함수의 결과값으로 바인딩하고, 그 프로퍼티에 접근할 때 get함수를 내부에서 실행시켜 새로운 값을 할당해준다.’ 로 받아들였다.
Set 메소드
정의하는 방법은 get과 같지만, arguments가 최소 한 개 이상 존재해야 한다는 점에서 조금 다르다.
사용법도 같다. 객체의 프로퍼티에 값을 할당하는것처럼 사용하면 알아서 setter함수가 작동한다. 메소드처럼 사용하기 위해 함수실행 연산자 ()를 붙이게 되면 같은 오류가 난다. ( … is not a function )
Inheritance: 상속
class SuperClass { }class SubClass extends SuperClass {
constructor() {
super(); // 꼭 써주어야 한다!
}
}
Java처럼 extends 키워드를 통해 클래스 상속이 가능하다. ( ‘ , ’ 를 이용한 다중상속 안됨 )
상속받는 클래스에서는 생성자 내부에서 super()를 통해 부모클래스의 생성자를 호출할 수 있는데, 이는 선택이 아니라 필수이다.
VM73165:1 Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
자식클래스의 생성자에서 super()를 호출하지 않았을 경우에 나는 에러이다. 정확하게는 인스턴스가 생성될 때 오류가 난다. Java에서와는 달리 super()를 default로 삽입해 주지 않는 것 같다. 자식클래스에서 생성자함수를 작성하지 않는다면, 당연히 붙이지 않아도 된다.
Mix-ins
우리는 믹스인 기법을 사용하여 클래스를 확장할 수 있다. 이 믹스인을 잘 사용한다면 재사용 가능한 기능들을 효율적으로 사용할 수 있을 것이다.
3–8번줄에 두 개의 믹스인함수를 만들었다. 클래스를 받아와 그것을 상속하는 익명클래스를 생성하고, 기능을 추가한 뒤 뱉어준다. 10번줄에서 볼 수 있듯이 여러번 중첩해서 사용할 수도 있다.
문득 생각이 들었다. 믹스인을 더 여러번 중첩해야 한다면? ()로 중첩되어 보기에 상당히 불편해질것 같다는 생각이 들었고 그걸 해소할 수 있는 함수를 13–17줄에 만들었다. reduce함수를 이용하여 인자로 넘긴 믹스인함수들을 차례로 누적실행하여 뱉어주는 함수이다.
믹스인이라는 기법에 대해 처음 알았고, 글을 쓰기 이전에 여러 사람들이 쓴 글을 읽어보았다. 그 중에 ‘믹스인을 사용하여 다중상속을 구현할 수 있다’는 말을 몇번 봤었는데, 옳은 말인지 의문이 생겼다.
다중상속을 구현하는게 아니라 기능적으로 흉내만 내는 것이라고 생각한다.
상속이라는게 관계가 성립할 때 이루어져야 하는 것인데 관계와는 상관없이 상속을 중첩하여 흉내내려고 하기에 그렇다. ( 위에서 sayHello와 sayBye는 관계도 없을 뿐더러 두 믹스인 순서가 뒤바뀌어도(상속관계가 뒤엎어져도) 상관없기 때문이다 )
'웹' 카테고리의 다른 글
JS Promise (2018.10.10) (0) | 2020.05.28 |
---|---|
JS this (2018.10.06) (0) | 2020.05.28 |
JS prototype (2018.10.01) (0) | 2020.05.28 |
Redux (2018.06.30) (0) | 2020.05.28 |
Immutable.js (2018.06.26) (0) | 2020.05.28 |