이 글은 드림코딩 유튜브 강의를 보며 학습한 내용을 정리한 JavaScript 복습 노트입니다
1. 객체 지향 프로그래밍(OOP) 개념
객체 지향 프로그래밍(OOP, Object-Oriented Programming)은 코드를 객체 단위로 구성하여 재사용성과 유지보수성을 높이는 방식입니다.
객체(Object)
- 속성(property)과 동작(method)를 가지는 데이터 구조입니다.
const car = {
brand: 'Tesla',
speed: 200,
drive: function () {
console.log('Driving fast!');
}
};
클래스(Class)
- 객체를 생성하기 위한 템플릿(template) 입니다.
- JavaScript에서는 ES6(ECMAScript 2015) 에서 도입되었습니다.
- 기존에는 프로토타입 기반의 상속을 사용했으나, 클래스를 도입하면서 가독성이 좋아졌고 문법이 간결해짐.
2. 클래스 선언(Class Declaration)
기본적인 클래스 구조
class Person {
constructor(name, age) {
this.name = name; // 인스턴스 필드
this.age = age;
}
speak() {
console.log(`${this.name}: hello!`);
}
}
const ellie = new Person('ellie', 20);
console.log(ellie.name); // "ellie"
console.log(ellie.age); // 20
ellie.speak(); // "ellie: hello!"
- class Person { ... }
- Person이라는 클래스를 선언 (클래스명은 대문자로 시작하는 것이 관례)
- constructor(name, age)
- 생성자 메서드. new 키워드로 객체를 생성할 때 자동으로 실행됨.
- this.name = name, this.age = age : 객체의 속성을 초기화.
- speak()
- speak() 메서드는 객체의 name 속성을 이용해 메시지를 출력.
- new Person('ellie', 20);
- Person 클래스의 인스턴스(객체)를 생성.
3. Getter와 Setter (게터와 세터)
class User {
constructor(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age; // 내부적으로 set age(value) 호출
}
get age() {
return this._age;
}
set age(value) {
this._age = value < 0 ? 0 : value; // 나이가 음수면 0으로 설정
}
}
const user1 = new User('Steve', 'Job', -1);
console.log(user1.age); // 0
get과 set 키워드
- Getter (get)
- user1.age 처럼 값을 가져올 때 실행되는 함수.
- return this._age; 로 age 값을 반환.
- Setter (set)
- user1.age = -1; 같은 방식으로 값을 설정할 때 실행됨.
- value < 0 ? 0 : value; 를 통해 음수 값 방지.
- _age 속성
- JavaScript에서 get과 set을 사용할 때, 무한 루프 방지를 위해 내부적으로 _age를 사용.
4. Public(공개) & Private(비공개) 필드
class Experiment {
publicField = 2; // 공개 필드 (모든 곳에서 접근 가능)
#privateField = 0; // 비공개 필드 (클래스 내부에서만 접근 가능)
}
const experiment = new Experiment();
console.log(experiment.publicField); // 2
console.log(experiment.privateField); // undefined (외부에서 접근 불가)
#privateField
- # 기호를 사용하여 클래스 내부에서만 접근 가능한 비공개 필드를 만듦.
- experiment.privateField를 출력하려고 하면 undefined가 출력됨.
5. 정적(static) 속성과 메서드
class Article {
static publisher = 'Dream Coding';
static printPublisher() {
console.log(Article.publisher);
}
}
console.log(Article.publisher); // "Dream Coding"
Article.printPublisher(); // "Dream Coding"
static 키워드
- 클래스 자체에 속하는 변수나 메서드.
- 인스턴스가 아닌 클래스명 자체로 접근해야 함 (Article.publisher).
6. 상속(Inheritance)
class Shape {
constructor(width, height, color) {
this.width = width;
this.height = height;
this.color = color;
}
draw() {
console.log(`drawing ${this.color} color!`);
}
getArea() {
return this.width * this.height;
}
}
class Triangle extends Shape {
draw() {
super.draw(); // 부모 클래스의 draw() 호출
console.log('🔺');
}
getArea() {
return (this.width * this.height) / 2; // 삼각형 면적 공식
}
toString() {
return `Triangle: color: ${this.color}`;
}
}
const triangle = new Triangle(20, 20, 'red');
triangle.draw(); // "drawing red color!" 🔺 출력
console.log(triangle.getArea()); // 200
extends 키워드
- class Triangle extends Shape
→ Shape 클래스를 상속하여 Triangle 클래스 생성.
super 키워드
- 부모 클래스의 메서드를 호출할 때 사용 (super.draw();).
7. instanceof 연산자
console.log(triangle instanceof Triangle); // true
console.log(triangle instanceof Shape); // true
console.log(triangle instanceof Object); // true (모든 객체는 Object의 인스턴스)
- instanceof 는 특정 객체가 해당 클래스를 기반으로 만들어졌는지 확인하는 연산자.
8. 객체 값 변경 확인 (참조형 데이터)
let obj = { value: 5 };
function change(value) {
value.value = 7;
}
change(obj);
console.log(obj); // { value: 7 }
- 객체는 참조(reference)로 전달되므로 함수 내부에서도 값이 변경됨.
🔍 추가 설명
1) Getter와 Setter 내부 _age 속성의 의미
get age() {
return this._age;
}
set age(value) {
this._age = value < 0 ? 0 : value;
}
- this.age = value; 할 때, 내부적으로 set age(value) 가 실행됨.
- 무한 재귀 호출을 방지하기 위해 this._age 라는 별도의 변수 사용.
- 만약 this.age = value; 를 그대로 할 경우, set age() 가 계속 호출되며 스택 오버플로우 오류(Stack Overflow) 발생.
2) Private 필드(#privateField)의 실제 동작 방식
class Experiment {
#privateField = 0;
}
const experiment = new Experiment();
console.log(experiment.privateField); // undefined
- JavaScript에서는 # 키워드를 붙여야만 해당 필드를 외부에서 직접 접근하지 못하게 보호 가능.
- experiment.#privateField 로 접근하려고 하면 SyntaxError 발생.
3) super.draw(); 가 호출되는 이유
class Triangle extends Shape {
draw() {
super.draw(); // 부모 클래스의 draw() 실행
console.log('🔺');
}
}
- super.draw(); 는 부모 클래스의 draw() 메서드를 호출.
- Shape 클래스를 상속했으므로, 기본적인 색상 출력 후 추가적인 동작을 수행할 수 있도록 확장.
4) 객체가 instanceof Object 가 되는 이유
console.log(triangle instanceof Object); // true
- JavaScript에서 모든 객체는 Object 를 상속 받음.
- Object는 JavaScript에서 모든 객체의 최상위 부모 클래스이므로, 어떤 객체든 instanceof Object 를 실행하면 true.
5) static 속성이 this 로 접근되지 않는 이유
class Article {
static publisher = 'Dream Coding';
static printPublisher() {
console.log(this.publisher); // 가능 (클래스에서 호출할 때)
}
}
const article1 = new Article();
console.log(article1.publisher); // undefined
- static 속성은 클래스 자체에 귀속 되기 때문에, article1.publisher 로 접근할 수 없음.
- 반드시 Article.publisher 처럼 클래스명으로 접근해야 함.