JavaScript에서 객체를 구현하는 방법은 아주 많습니다.
- 객체 리터럴을 이용해서 선언
- Factory 함수를 이용해서 객체 리터럴로 반환
- 생성자 함수를 이용해서, 객체를 선언한 뒤, new로 할당
위의 3가지 방법 외에도 , ES6에서 정의된 방법이 1개가 있습니다. 어쩌면 가장 친숙한(?) 방법일지도 모릅니다. 바로 Class 문법입니다. 각각의 방법마다 차이점은 있긴 합니다! 하지만, 그건 OOP 디자인패턴을 다루면서 더욱 자세히 하겠습니다.(Prototype에 대한 심화설명 + 다양한 패턴에서 Prototype의 쓰임, TypeScript의 등장 등등)
Class
- Constructor(생성자)와 new를 이용해서, 객체를 생성합니다.
- method를 정의해서 사용할 수 있습니다.
- 사실 Game이라는 함수를 생성하게 됩니다(?)
class Game{
constructor(){} //생성자
method1(){}
method2(){}
...
}
game = new Game();
위의 문법도 대부분의 상황에서는 Factory 함수를 쓰든 , 생성자 함수를 쓰든 상관이 없을겁니다. 하지만, class 문법과 생성자 함수가 같다면, var을 let과 const로 대체한 것처럼 완벽히 대체되었겠죠! 미묘한 차이가 있습니다.
자바스크립트의 클래스 원리
클래스의 선언(declare)부분
class Game{
constructor(){
...
}
method1(){
...
}
}
console.log(typeof Game); //function
console.log(Game === Game.prototype.constructor); //true
Game();//error
- Game이라는 함수를 만듭니다. 함수의 내용(로직)은 constructor에 정의되어 있는 부분을 가져옵니다.
- 클래스 내에서 정의한 메서드를 Game.prototype에 저장합니다.
- 클래스로 만든 함수에는 내부 프로퍼티인 [[IsClassConstructor]] :true로 붙게됩니다. 따라서, 일반함수처럼 호출이 불가능해집니다.
- 클래스는 항상 엄격모드로 실행 됩니다.(use strict)
클래스의 "할당"(allocation)부분
- new로 Game이라는 함수가 불려지는 순간, Game이라는 객체 리터럴을 만들게 되고, 메서드들은 Game.prototype을 참조하는 형태로 만들어집니다.
그림으로 표현하면, 아래와 같이 됩니다.
클래스와 생성자 함수의 차이점
- 클래스로 만든 함수에는 내부 프로퍼티인 [[IsClassConstructor]] :true로 붙게됩니다. 따라서, 일반함수처럼 호출이 불가능해집니다.
- 클래스는 항상 엄격모드로 실행 됩니다.(use strict) 따라서, this가 undefined가 기본이 되겠죠?
주의점)
- 비동기 함수로 메소드를 넘길 때, 메소드 내부에 this가 있다면 원하는 코드가 나오지 않습니다. JS의 this는 호출할 때, 결정이 되기 때문에 비동기 함수와 같이 쓰게 된다면 의도치 않은 결과를 낼 수 있습니다.
class Button{
constructor(value){
this.value=value;
}
click(){
console.log(this.value);
}
}
const btn = new Button("hello!");
setTimeout(btn.click,1000); //undefined? or hello!
위의 코드는 undefined입니다. 따라서, btn.click을 보면 아직 "호출"을 안해줘서 문제가 생긴겁니다.
class Button{
constructor(value){
this.value=value;
}
click(){
console.log(this.value);
}
}
const btn = new Button("hello!");
setTimeout(()=>btn.click(),1000); //undefined? or hello!
비동기 함수에서 method losing this 현상 방지하기
- arrow function으로 반환하는 형태로 작성한다면 , 이미 click()은 Button 객체에 bind되었기 때문에, 우리가 의도한 대로 "hello!"가 나오게 됩니다.
- Bind함수 (call,apply,bind)를 이용해도 됩니다.
- click() function 자체를 화살표 함수로 구현하는 방법도 있습니다. 단 , 화살표 함수는 Prototype을 생성하지 않기 때문에, 테스트 케이스 작성(mocking)이 불가능할 수 있습니다. 프로토타입이 없으니, 상속도 불가능하게 됩니다.
'Web Front-end > JavaScript' 카테고리의 다른 글
[JS/Basic/배열/Array] 자바스크립트의 배열 (0) | 2022.08.23 |
---|---|
[JS/Event/Pattern] 자바스크립트 이벤트 버블링(Event Bubbling)과 이벤트 위임(Event Delegation) (0) | 2022.08.22 |
[JS/Basic/객체] 자바스크립트 객체(new,factory,ProtoType) (0) | 2022.08.01 |
[JS/Basic/자료형] 자바스크립트 원시타입,참조타입 (0) | 2022.07.29 |
[JS/Basic/연습문제] 자바스크립트 객체 연습문제 (0) | 2022.07.29 |