[JS] 10. 클래스
📚 Table of Contents
01. prototype
프로토타입(prototype)은 자바스크립트의 객체 지향 프로그래밍의 핵심 개념입니다.
이는 객체들 사이에서 속성과 메서드를 공유하는 메커니즘을 제공합니다.
주요 특징:
- 상속 : 객체는 프로토타입으로부터 속성과 메서드를 상속받습니다.
- 메모리 효율성 : 여러 객체가 동일한 프로토타입을 공유하여 메모리를 절약합니다.
- 동적 수정 : 프로토타입은 런타임에 수정할 수 있어 유연성을 제공합니다.
프로토타입 체인:
객체의 프로퍼티나 메서드를 찾을 때, 자바스크립트 엔진은 해당 객체에서 시작하여 프로토타입 체인을 따라 올라가며 검색합니다.
prototype
속성을 통해 새로운 메서드를 추가할 수 있습니다. 이를 통해 모든 인스턴스가 공유할 수 있는 공통 메서드를 정의할 수 있습니다.
예를 들어, 배열의 prototype
에 새로운 메서드를 추가하면 모든 배열 인스턴스에서 해당 메서드를 사용할 수 있습니다.
// const fruits = ['Apple', 'Banana', 'Cherry'] 리터럴 방식
const fruits = new Array('Apple', 'Banana', 'Cherry') // 생성자 함수
console.log(fruits) // ['Apple', 'Banana', 'Cherry']
console.log(fruits.length) // 3
console.log(fruits.includes('Apple')) // True
console.log(fruits.includes('Orange')) // False
// Array.prototype에 새로운 메서드 'ex'를 추가합니다.
Array.prototype.ex = function () {
console.log(this) // 이 메서드는 배열 자체를 로그로 출력합니다.
}
// 'fruits' 배열에 'ex' 메서드를 호출합니다.
fruits.ex() // ['Apple', 'Banana', 'Cherry']
// 새로운 빈 배열 'arr'를 생성합니다.
const arr = []
// 'arr' 배열에 'ex' 메서드를 호출합니다.
arr.ex() // []
function User(first, last) {
this.firstName = first
this.lastName = last
}
// User.prototype에 getFullName 메서드를 추가합니다.
User.prototype.getFullName = function () {
return `${this.firstName} ${this.lastName}`
}
// User 클래스의 인스턴스를 생성합니다.
const neu = new User('Neu', 'Park')
const neo = new User('Neo', 'Park')
// 생성된 인스턴스를 로그로 출력합니다.
console.log(neu)
// User {firstName: 'Neu', lastName: 'Park'}
console.log(neo)
// User {firstName: 'Neo', lastName: 'Park'}
// getFullName 메서드를 호출하여 사용자 이름을 로그로 출력합니다.
console.log(neu.getFullName()) // Neu Park
console.log(neo.getFullName()) // Neo Park
02. ES6 Class와 프로토타입 비교
ES6에서 도입된 클래스와 기존의 프로토타입 기반 상속 방식을 비교해보겠습니다.
문법적 차이:
1. 클래스 선언
// 클래스
class User {
constructor(name) {
this.name = name;
}
}
// 프로토타입
function User(name) {
this.name = name;
}
2. 메서드 정의
// 클래스
class User {
sayHello() {
console.log(`안녕하세요, ${this.name}입니다.`);
}
}
// 프로토타입
User.prototype.sayHello = function() {
console.log(`안녕하세요, ${this.name}입니다.`);
};
주요 차이점:
- 가독성: 클래스는 더 직관적이고 깔끔한 문법을 제공합니다.
- 호이스팅: 클래스는 호이스팅되지 않지만, 함수 선언은 호이스팅됩니다.
- 엄격 모드: 클래스 내부 코드는 자동으로 엄격 모드로 실행됩니다.
- 생성자: 클래스는 new 키워드 없이 호출할 수 없습니다.
유사점:
- 내부 동작: 클래스도 결국 프로토타입 기반으로 동작합니다.
- 인스턴스 생성: 둘 다 new 키워드로 인스턴스를 생성합니다.
클래스 는 프로토타입 기반 상속의 "문법적 설탕" 입니다. 더 명확하고 사용하기 쉬운 객체 지향 프로그래밍 방식을 제공합니다.
03. Getter, Setter
Getter와 Setter는 객체 지향 프로그래밍에서 중요한 개념입니다.
Getter
- Getter는 객체의 속성 값을 읽는 메서드입니다.
- 속성에 접근할 때 자동으로 호출됩니다.
get
키워드를 사용하여 정의합니다.
Setter
- Setter는 객체의 속성 값을 설정하는 메서드입니다.
- 속성에 값을 할당할 때 자동으로 호출됩니다.
set
키워드를 사용하여 정의합니다.
장점
- 데이터 검증: 값을 설정하기 전에 유효성을 검사할 수 있습니다.
- 계산된 속성: 다른 속성을 기반으로 값을 동적으로 계산할 수 있습니다.
- 캡슐화: 내부 구현을 숨기고 인터페이스만 노출할 수 있습니다.
// User 클래스 선언
class User {
// 생성자 메서드
constructor(first, last) {
this.firstName = first
this.lastName = last
}
// fullName 속성의 Getter 메서드
get fullName() {
return `${this.firstName} ${this.lastName}`
}
// fullName 속성의 Setter 메서드
set fullName (value) {
;[this.firstName, this.lastName] = value.split(' ')
}
}
// User 클래스의 인스턴스 생성
const neu = new User('Neu', 'Park')
// fullName 속성의 Getter 메서드 호출
console.log(neu.fullName)
// fullName 속성의 Setter 메서드 호출
neu.fullName = 'Neo Anderson'
// fullName 속성의 Getter 메서드 호출
console.log(neu.fullName)
04. 정적 메소드
프로토타입 메소드와 정적 메소드는 클래스에서 사용되는 두 가지 다른 유형의 메소드입니다.
프로토타입 메소드
- 인스턴스에서 직접 호출할 수 있습니다.
- 객체의 프로토타입에 정의됩니다.
- 인스턴스 속성에 접근할 수 있습니다.
- 'this'는 메소드를 호출한 인스턴스를 가리킵니다.
정적 메소드
- 클래스 자체에서 호출됩니다.
- 'static' 키워드를 사용하여 정의합니다.
- 인스턴스 속성에 직접 접근할 수 없습니다.
- 'this'는 클래스 자체를 가리킵니다.
차이점
- 호출 방식: 프로토타입 메소드는 인스턴스에서, 정적 메소드는 클래스에서 호출합니다.
- 인스턴스 접근: 프로토타입 메소드는 인스턴스 속성에 접근 가능하지만, 정적 메소드는 불가능합니다.
- 메모리 사용: 프로토타입 메소드는 모든 인스턴스가 공유하지만, 정적 메소드는 클래스에 하나만 존재합니다.
각 메소드 유형은 상황에 따라 적절히 선택하여 사용해야 합니다.
class User {
constructor(first, last) {
this.firstName = first
this.lastName = last
}
getFullName() { // prototype 메소드
return `${this.firstName} ${this.lastName}`
}
static isUser(user) { // 정적 메소드
if (user.firstName && user.lastName) {
return true
}
return false
}
}
const neu = new User('Neu', 'Park')
const neo = new User('Neo', 'An')
const lewis = {
name: 'lewis Yang',
age: 85
}
console.log(neu)
console.log(neo)
console.log(User.isUser(neu)) // true
console.log(User.isUser(lewis)) // false
05. 상속과 instanceof
자바스크립트에서 클래스는 상속을 지원합니다.
상속은 한 클래스가 다른 클래스의 속성과 메서드를 상속받는 것을 의미합니다.
예를 들어, '자전거' 클래스가 '운송수단' 클래스를 상속받으면, '자전거' 클래스는 '운송수단' 클래스의 모든 속성과 메서드를 사용할 수 있습니다.
이를 통해 코드의 재사용성을 높이고, 유지보수를 쉽게 할 수 있습니다.
instanceof
연산자는 객체가 특정 클래스의 인스턴스인지 확인하는 데 사용됩니다.
예를 들어, '자전거' 클래스의 인스턴스가 '자전거' 클래스의 인스턴스인지 확인하려면, 'instanceof' 연산자를 사용합니다.
이를 통해 객체가 어떤 클래스의 인스턴스인지 확인하고, 그에 따라 적절한 동작을 수행할 수 있습니다.
// * 운송수단
class Vehicle {
constructor(acceleration = 1) {
this.speed = 0
this.acceleration = acceleration
}
accelerate() {
this.speed += this.acceleration
}
decelerate() {
if (this.speed <= 0) {
console.log('정지!')
return
}
this.speed -= this.acceleration
}
}
// * 자전거
class Bicycle extends Vehicle {
constructor(price = 100, acceleration) {
super(acceleration)
this.price = price
this.wheel = 2
}
}
const bicycle = new Bicycle(300)
bicycle.accelerate()
bicycle.accelerate()
console.log(bicycle)
console.log(bicycle instanceof Bicycle) // true
console.log(bicycle instanceof Vehicle) // true
// * 자동차
class Car extends Bicycle {
constructor(license, price, acceleration) {
super(price, acceleration)
this.license = license
this.wheel = 4
}
// 오버라이딩
accelerate() {
if (!this.license) {
console.error('무면허!')
return
}
this.speed += this.acceleration
console.log('가속!', this.speed)
}
}
const carA = new Car(true, 7000, 10)
const carB = new Car(false, 4000, 6)
carA.accelerate() // 가속! 10
carA.accelerate() // 가속! 20
carB.accelerate() // 무면허 !
console.log(carA)
console.log(carB)
console.log(carA instanceof Car) // true
console.log(carA instanceof Bicycle) // true
console.log(carA instanceof Vehicle) // true
// * 보트
class Boat extends Vehicle {
constructor(price, acceleration) {
super(acceleration)
this.price = price
this.motor = 1
}
}
const boat = new Boat(10000, 5)
console.log(boat)
console.log(boat instanceof Boat) // true
console.log(boat instanceof Vehicle) // true
console.log(boat instanceof Bicycle) // false
06. instanceof 와 constructor
instanceof
키워드는 클래스의 인스턴스 여부를 확인하는 데 사용됩니다.
이를 통해 특정 클래스의 인스턴스인지, 또는 그 클래스를 상속받은 클래스의 인스턴스인지 확인할 수 있습니다.
예를 들어, class B extends A
인 경우, b instanceof A
는 true
를 반환합니다.
즉, instanceof
는 클래스의 상속 계층 구조를 고려하여 비교를 수행합니다.
반면, constructor
속성과 일치연산자(===
)를 사용하면, 특정 클래스의 인스턴스인지 여부를 더 정확하게 확인할 수 있습니다.
constructor
속성은 객체의 생성자 함수를 반환합니다.
따라서, a.constructor === A
와 같이 사용하면, a
가 A
클래스의 직접적인 인스턴스인지 여부를 확인할 수 있습니다.
이 방법은 instanceof
와 달리, 클래스의 상속 계층 구조를 고려하지 않습니다.
즉, a
가 A
클래스를 직접 상속받지 않더라도, A
클래스를 상속받은 다른 클래스의 인스턴스라면 false
를 반환합니다.
class A {
constructor() {}
}
class B extends A {
constructor() {
super()
}
}
class C extends B {
constructor() {
super()
}
}
// a 는 하나의 인스턴스
const a = new A() // 생성자 함수
const b = new B()
const c = new C()
console.log(a instanceof A) // true
console.log(a instanceof B) // false
console.log(b instanceof A) // true
console.log(b instanceof B) // true
console.log(b instanceof C) // false
console.log(c instanceof A) // true
console.log(c instanceof B) // true
console.log(c instanceof C) // true
console.log(c.constructor === A) // false
console.log(c.constructor === B) // false
console.log(c.constructor === C) // true
'Language > JavaScript' 카테고리의 다른 글
[JS] 09. 함수 (2) | 2024.10.21 |
---|---|
[JS] 08. 조건문, 반복문 (1) | 2024.10.18 |
[JS] 07. 구조 분해 할당, 선택적 체이닝 (0) | 2024.10.17 |
[JS] 06. 연산자 (1) | 2024.10.15 |
[Js] 05. 데이터 etc (0) | 2024.10.14 |