일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 개발자취업
- 방송대컴퓨터과학과
- 데이터베이스시스템
- 파이썬
- JavaScript
- Git
- node.js
- presignedurl
- 꿀단집
- SQL
- 중간이들
- TiL
- aws
- Python
- 코딩테스트
- 항해99
- MySQL
- 코드잇
- CSS
- 엘리스sw트랙
- 코딩테스트준비
- 파이썬프로그래밍기초
- nestjs
- Cookie
- 유노코딩
- 방송대
- HTML
- redis
- 프로그래머스
- 99클럽
- Today
- Total
배꼽파지 않도록 잘 개발해요
[코드잇] 자바스크립트 객체 지향 기본기 본문
1. 객체와 클래스
객체 지향과 절차 지향
• 객체 지향 프로그래밍 : 프로퍼티와 메소드로 이루어진 각 객체들의 상호작용을 중심으로 코드를 작성하는 것
• 절차 지향 프로그래밍 : 변수와 함수를 가지고 작업의 순서에 맞게 코드를 작성하는 것
객체만들기
Object-Literal
· 객체를 나타내는 문자열
· 중괄호 안에 프로티와 메소드를 나열
- 프로퍼티 : 객체의 상태를 나타내는 변수들 / email, birthdate
- 메소드 : 객체의 행동을 나타내는 함수들 / buy(item)
this : 현재 객체 자체를 의미 (user)
this.email : user의 email 프로퍼티
const user = {
email: 'gildong@google.com',
birthday: '1992-03-03',
buy(item) {
console.log(`${this.email} buys ${item.name}`);
},
}
const item = {
name: '스웨터',
price: 30000,
};
console.log(user.email); // gildong@google.com
console.log(user['email']); // gildong@google.com
console.log(user.birthday); // 1992-03-03
user.buy(item); // gildong@google.com buys 스웨터
Factory function
객체를 생성하는 함수
비슷한 내용의 객체를 이름만 다르게 하여 생성하는 경우
const user1 = {
email: 'gildong@google.com',
birthday: '1982-03-03',
buy(item) {
console.log(`${this.email} buys ${item.name}`);
},
}
const user2 = {
email: 'dooly@google.com',
birthday: '1002-03-03',
buy(item) {
console.log(`${this.email} buys ${item.name}`);
},
}
이런 식으로 계속 많은 수의 객체를 생성하면 코드의 양이 기하급수적으로 늘어남.
함수 안에 객체를 만들고, 해당 객체를 리턴함.
function createUser(email, birthdate) {
const user = {
email: email,
birthdate: birthdate,
buy(item) {
console.log(`${this.email} buys ${item.name}`);
},
};
return user;
}
const item = {
name: '스웨터',
price: 30000,
};
const user1 = createUser('dooly@google.com', '1002-03-03');
const user2 = createUser('gildong@google.com', '1982-03-03');
console.log(user1.email); // dooly@google.com
console.log(user2.email); // gildong@google.com
user1.buy(item); // dooly@google.com buys 스웨터
user2.buy(item); // gildong@google.com buys 스웨터
이 코드는 팩토리 함수인 'createUser'을 사용하여 user 객체를 생성함.
프로퍼티 네임과 파라미터가 같은 경우 값 대입하는 부분 생략 가능함.
function createUser(email, birthdate) {
const user = {
email,
birthdate,
buy(item) {
console.log(`${this.email} buys ${item.name}`);
},
};
return user;
}
Constructor function
객체를 생성하는 용도로 사용하는 Constructor function을 정의하고, 그 안에서 this 키워드를 사용하여 생성될 객체의 프로퍼티와 메소드를 설정하는 방법
this가 매번 생성되는 해당 객체를 가리킴
생성되는 객체의 프로퍼티와 매소드가 매번 달라지는 것임.
• constructor function은 호출시에는 앞에 new를 붙여야 됨.
• constructor function은 함수의 이름이 대문자로 시작함. (관습)
function User(email, birthdate) {
this.email = email;
this.birthdate = birthdate;
this.buy = function (item) {
console.log(`${this.email} buys ${item.name}`);
};
}
const item = {
name: '스웨터',
price: 30000,
};
const user1 = new User('dooly@google.com', '1002-03-03');
const user2 = new User('gildong@google.com', '1982-03-03');
console.log(user1.email); // dooly@google.com
console.log(user2.email); // gildong@google.com
console.log(user1.birthdate); // 1002-03-03
console.log(user2.birthdate); // 1982-03-03
user1.buy(item); // dooly@google.com buys 스웨터
user2.buy(item); // dooly@google.com buys 스웨터
Class
ES6(2015)에서는 class라는 키워드가 추가됨.
프로퍼티는 constructor 안에, 메소드는 바깥에 분리해서 씀.
class User {
constructor(email, birthdate) {
this.email = email;
this.birthdate = birthdate;
}
buy(item) {
console.log(`${this.email} buys ${item.name}`);
}
}
const item = {
name: '스웨터',
price: 30000,
};
const user1 = new User('dooly@abc.com', '1002-02-02');
console.log(user1.email); // dooly@abc.com
console.log(user1.birthdate); // 1002-02-02
user1.buy(item); // dooly@abc.com buys 스웨터
const user2 = new User('gildong@abc.com', '1982-02-02');
console.log(user2.email); // gildong@abc.com
console.log(user2.birthdate); // 1982-02-02
user2.buy(item); // gildong@abc.com buys 스웨터
2. 객체 지향 프로그래밍의 4개의 기둥
추상화
· 어떤 구체적인 존재를 원하는 방향으로 간략화해서 나타내는 것
· 클래스 설계도 추상화 과정에 해당됨.
· 클래스와 프로퍼티, 메소드 이름을 직관적으로 알기 쉽게 지어야 함.
· 부족하면 추가적으로 주석을 달거나 별도의 설명 문서를 작성함.
캡슐화
· 특정 프로퍼티에 대한 접근을 미리 정해진 메소드들을 통해서만 가능하도록 하는 것
· 숨기고자 하는 프로퍼티 이름에 언더바(_)를 씀.
· 사용자가 객체 내부의 프로퍼티 값을 이상하게 설정하는 것을 방지, 안정성 높임
setter 메소드로 이메일 유효성 검사 예시
class User {
constructor(email, birthdate) {
this.email = email;
this.birthdate = birthdate;
}
buy(item) {
console.log(`${this.email} buys ${item.name}`);
}
// setter 메소드로 유효성 검사
set email(address) {
if (address.includes('@')) {
this._email = address;
} else {
throw new Error('invalid email address');
}
}
}
const item = {
name: '스웨터',
price: 30000,
};
const user1 = new User('dooly@abc.com', '1002-02-02');
user1.email = 'dooly'; // 이메일 형식이 아님.
console.log(user1._email);
getter 메소드와 setter 메소드를 작성
class User {
constructor(email, birthdate) {
this.email = email;
this.birthdate = birthdate;
}
buy(item) {
console.log(`${this.email} buys ${item.name}`);
}
// getter 메소드
get email() {
return this._email;
}
// setter 메소드로 유효성 검사
set email(address) {
if (address.includes('@')) {
this._email = address;
} else {
throw new Error('invalid email address');
}
}
}
const item = {
name: '스웨터',
price: 30000,
};
const user1 = new User('dooly@abc.com', '1002-02-02');
console.log(user1.email); // dooly@abc.com
getter 메소드
· email의 속성값을 가져오기 위해 사용됨.
· 실제 값은 '_email'이라는 프라이빗 속성에 저장되어 있으나, 외부에서는 마치 객체의 직접적인 속성인 것처럼 접근 가능함.
console.log(user1.email);
email 프로퍼티 값이 직접 읽혀지는게 아니라 email의 getter 메소드가 실행됨.
setter 메소드
· email 속성값을 설정하기 위해 사용함.
· 유효한 이메일 주소만 저장하도록 보장함.
하지만 다음과 같이 여전히 변수에 직접 접근 가능함.
console.log(user1._email);
user1._email = 'chris robert';
Java - Private 키워드
JavaScript - 캡슐화를 자체적으로 지원하는 문법이 없음.
클로저
· 자바스크립트에서 어떤 함수와 그 함수가 참조할 수 있는 값들로 이루어진 환경을 하나로 묶은 것
→ 이를 통해 캡슐화를 할 수 있음.
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);
user 객체가 생성될 때 get과 set 메서드가 _email 변수에 대한 클로저를 형성하게 됨.
user 객체가 반환되면서 createUser 함수의 실행은 종료됨.
하지만 get과 set메서드는 여전히 _email에 접근할 수 있음.
클로저로 잘 캡슐화되었는지 확인하는 방법
console.log( Object.getOwnPropertyNames(user1) );
캡슐화된 변수 _email이 user1 객체에 존재하지 않는 것을 확인할 수 있음.
상속
· 상속을 적용하면 두 클래스 간의 공통된 부분은 부모클래스에 적기
· 자식클래스는 부모 클래스와 겹치는 부분을 제외하고 적으면 됨.
→ 코드의 재사용성이 좋아짐.
· 자식클래스로 객체를 만드려고 할 때는 반드시 그 생성자 함수 안에서 super을 호출해서 부모 클래스의 생성자 함수를 먼저 호출해줘야 함.
// 부모 클래스
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}`);
}
}
const item = {
name: '스웨터',
price: 30000,
}
const pUser1 = new PremiumUser('dooly@google.com', '1002-02-02', 'gold');
console.log(pUser1.email); // dooly@google.com
console.log(pUser1.birthdate); // 1002-02-02
console.log(pUser1.level); // gold
pUser1.buy(item); // dooly@google.com buys 스웨터
pUser1.streamMusicForFree(); // Free music Streaming for dooly@google.com
자식 클래스에 적을 것
- extends 클래스A : 클래스A를 상속받는다
- constructor 안에 super
다형성
· 하나의 변수가 다양한 종류의 객체를 가리킬 수 있는 것
· 오버라이딩(overriding) : 자식 클래스에서 부모 클래스와 동일한 이름의 메소드를 정의하고, 그 내용을 다르게 채우는 것
· 부모 클래스와 다른 프로퍼티나 메소드 사용 가능 : super(프로퍼티), super.메소드
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) {
super.buy(item); // 부모 클래스의 메소드
this.point += item.price * 0.05; // 자식 클래스에만 추가한 메소드
}
streamMusicForFree() {
console.log(`Free music streaming for ${this.email}`);
}
}
const item = {
name: '스웨터',
price: 300000,
};
const user1 = new User('chris123@google.com', '19920321');
const user2 = new User('rache@google.com', '19880516');
const user3 = new User('brian@google.com', '20051125');
const pUser1 = new PremiumUser('tommy@google.com', '19901207', 3);
const pUser2 = new PremiumUser('helloMike@google.com', '19900915', 2);
const pUser3 = new PremiumUser('alicekim@google.com', '20010722', 5);
const users = [user1, pUser1, user2, pUser2, user3, pUser3];
users.forEach((user) => {
user.buy(item);
});
instance of 연산자
· 객체가 특정 클래스의 인스턴스인지 확인할 수 있음.
· 현재 변수가 가리키는 객체가 정확히 어느 클래스로 만든 객체인지 확인하고 싶은 경우
· 가능하면 남용하지 말고, 다형성을 활용한 코드를 작성하자.
현재 user 객체가 부모 클래스에서 만든 거, pUser 객체는 자식 클래스에서 만든 것임.
users.forEach((user) => {
console.log(user instanceof PremiumUser);
});
users.forEach((user) => {
console.log(user instanceof User);
});
자식 클래스로 만든 객체는 부모 클래스로 만든 객체로도 인정됨.
static 프로퍼티와 static 메소드
· 클래스 자체에 속하는 프로퍼티나 메소드로, 클래스의 인스턴스를 생성하지 않고도 바로 접근할 수 있음.
class Math {
static PI = 3.14;
static getCircleArea(radius) {
return Math.PI * radius * radius;
}
}
console.log(Math.PI);
console.log(Math.getCircleArea(5));
'코드잇 Codeit > Front-End' 카테고리의 다른 글
[코드잇] 자바스크립트 모듈 (0) | 2024.01.06 |
---|---|
[코드잇] 자바스크립트 웹 개발 기본기 ③ - async/await을 활용한 세련된 비동기 코드 (0) | 2024.01.05 |
[코드잇] 자바스크립트 웹 개발 기본기 ② - 비동기 실행과 Promise 객체 (0) | 2023.12.29 |
[코드잇] 자바스크립트 웹 개발 기본기 ① - 웹 기초 다지기, Web API 배우기 (0) | 2023.12.26 |
[코드잇] 인터랙티브 자바스크립트 ② - 이벤트 살펴보기, 다양한 이벤트 (0) | 2023.12.25 |