→ ‘객체’간의 상호작용을 중심으로 하는 프로그래밍
→ 프로퍼티와 메소드로 이루어진 각 객체들의 상호 작용을 중심으로 코드를 작성하는 것
VS 절차 지향 프로그래밍
→ 변수와 함수를 가지고 작업의 순서에 맞게 코드를 작성하는 것
Object-Literal
→ 객체를 나타내는 문자열
→ 자바스크립트에서 객체를 생성할 수 있는 가장 기본적인 방법
Factory Function
→ 객체를 생성해서 리턴하는 함수
function createUser(email, birthdate) {
const user = {
email,
birthdate,
buy(item) {
console.log(`${this.email} buys ${item.name}`);
},
};
return user;
}
const user1 = createUser("chirs123@google.com", "1992-03-21");
Constructor Function (생성자 함수)
→ 객체를 생성할 수 있는 함수
this
: 매번 생성되는 해당 객체를 가리키는 역할
new
를 붙여서 호출해야 해야 객체 생성 가능대문자
로 시작function User(email, birthdate) {
(this.email = email),
(this.birthdate = birthdate),
(this.buy = function (item) {
console.log(`${this.email} buys ${item.name}`);
});
}
const user1 = new User("chirs123@google.com", "1992-03-21");
Class
constructor
(생성자) : 객체가 생성될 때 실행
this
: 생성되는 객체를 나타냄
class User {
constructor(email, birthdate) {
this.email = email;
this.birthdate = birthdate;
}
buy(item) {
console.log(`${this.email} buys ${item.name}`);
}
}
const user1 = new User("chirs123@google.com", "1992-03-21");
생략
class Car {
constructor(color, speed) {
this.color = color;
this.speed = speed;
}
run() {
console.log(`Runs at ${this.speed}`);
}
}
const car1 = new Car('blue', '100km/h');
car1.run();
객체 지향 프로그래밍이 가능한 언어의 2가지 종류
Java
JavaScript
🔅 객체 지향 프로그래밍의 4가지 기둥
1. 추상화
2. 캡슐화
3. 상속
4. 다형성
→ 어떤 구체적인 존재를 원하는 방향으로 간략화해서 나타내는 것
ex. class를 설계하는 것
→ 객체의 특정 프로퍼티에 직접 접근하지 못하도록 막는 것
getter
, setter
메소드class User {
constructor(email, birthdate) {
this.email = email; **// email은 setter 메소드의 이름이 됨**
this.birthdate = birthdate;
}
buy(item) {
console.log(`${this.email} buys ${item.name}`);
}
**// getter 메소드 -> 프로퍼티의 값을 구하는 함수**
get email() {
return this._email;
}
**// setter 메소드**
set email(address) {
**// email 프로퍼티에 값을 설정할 때 사용**
if (address.includes("@")) {
**// _가 붙은 _email이라는 새로운 프로퍼티, 숨기고자 하는 프로퍼티의 이름**
this._email = address;
} else {
throw new Error("invalid email address");
}
}
}
const user1 = new User("chirs123@google.com", "1992-03-21");
console.log(user1.email); **// getter 메소드 사용시 _ 없이 변수 사용 가능**
완벽한 캡슐화를 하는 법
→ 클로저(Closure) : 어떤 함수와 그 함수가 참조할 수 있는 값들로 이루어진 환경을 하나로 묶은 것
클로저라는 개념으로 해당 환경을 함수와 함께 그대로 유지시켜주어 _email
변수에 접근 가능
클로저가 아닌 경우에는 아래와 같이 _email
변수에 접근 불가
function createUser(email, birthdate) {
let _email = email;
const user = {
birthdate,
get email() {
return _email;
},
set email(address) {
if (address.includes('@')) {
_email = address;
} else {
throw new Error('invalid email address');
}
},
};
return user;
}
const user1 = createUser('chris123@google.com', '19920321');
console.log(user1._email); // _ 추가 -> 접근 불가
function createUser(email, birthdate) {
const _email = email;
let _point = 0;
function increasePoint() {
_point += 1;
}
const user = {
birthdate,
get email() {
return _email;
},
get point() {
return _point;
},
buy(item) {
console.log(`${this.email} buys ${item.name}`);
increasePoint();
},
};
return user;
}
const item = {
name: '스웨터',
price: 30000,
};
const user1 = createUser('chris123@google.com', '19920321');
user1.buy(item);
user1.buy(item);
user1.buy(item);
console.log(user1.point);
user1.increasePoint(); // user1 객체로 increasePoint 직접 호출 불가
→ increasePoint
가 유저 객체 안에서 적절한 곳에 사용되어야 하고, 아무렇게나 함부로 호출해서는 안 되는 메소드라고 가정하고 캡슐화
user1
객체에는 increasePoint
라는 메소드가 없기 때문에 직접 호출 불가→ 하나의 객체가 다른 객체의 프로퍼티와 메소드를 물려받는 것
extends
를 통해 상속을 받아 중복 코드 삭제 → 코드의 재사용성이 좋아짐super
를 통해 부모 클래스의 constructor
를 호출해주어야 실행 가능class User { // 부모 클래스
constructor(email, birthdate) {
this.email = email;
this.birthdate = birthdate;
}
buy(item) {
console.log(`${this.email} buys ${item.name}`);
}
}
class PremiumUser extends User { // 자식 클래스
constructor(email, birthdate, level) {
super(email, birthdate);
this.level = level;
}
streamMusicForFree() {
console.log(`Free music streaming for ${this.email}`);
}
}
→ 많은 형태를 갖고 있는 성질
Overriding(오버라이딩)
: 덮어써서 작성class User {
// 부모 클래스
constructor(email, birthdate) {
this.email = email;
this.birthdate = birthdate;
}
buy(item) {
console.log(`${this.email} buys ${item.name}`);
}
}
class PremiumUser extends User {
// 자식 클래스
constructor(email, birthdate, level, point) {
super(email, birthdate);
this.level = level;
this.point = point;
}
buy(item) {
// console.log(`${this.email} buys ${item.name}`);
super.buy(item); // 부모 클래스의 buy 메소드를 호출 (동일한 내용을 호출 후 오버라이딩)
this.point += item.price * 0.05;
}
streamMusicForFree() {
console.log(`Free music streaming for ${this.email}`);
}
}
→ 현재 변수가 가르키는 객체가 어느 클래스로 만든 객체인지 확인하는 역할
console.log(user instanceof User); // true, false
console.log(user instanceof PremiumUser); // true, false
→ 자식 클래스로 만든 객체는 부모 클래스로 만든 객체로도 인정됨❗
→ 클래스에 직접적으로 딸려있는 프로퍼티와 메소드
→ 객체가 아닌 클래스 자체로 접근!
class Math {
static PI = 3.14;
static getCircleArea(radius) {
return Math.PI * radius * radius;
}
}
Math.PI = 3.141592;
Math.getCircleArea = function (width, height) {
return width * height;
};
console.log(Math.PI);
console.log(Math.getCircleArea(4, 5));
➕ console.log(Date.now());
생략
→ 파일 하나당 클래스 하나를 작성하고, 이를 외부에 공개해서 사용할 수 있도록 하는 방식을 주로 활용한다❗