객체지향 프로그래밍의 핵심
여기서 객체(object)는 말 그대로 사물
{ num: 1 }데이터 타입 아님
하지만, 클래스는 결국 { num: 1 } 처럼 생긴 객체(object)를 잘 설계하기 위한 틀은 맞음.
객체는 특정 로직을 갖고 있는 행동(method)와 변경 가능한 상태(멤버 변수)를 가짐
원하는 구조의 객체 틀을 짜놓고, 비슷한 모양의 객체를 공장처럼 찍어낼 수 있음.
객체를 매번 만들어서 사용해도 좋지만, 큰 큐모의 객체 이거나 비슷한 모양의 객체를 계속 만들어야 한다면,class라는 설계도를 통해 만들 수 있음.
let ray = {
name: 'Ray',
price: 2000000,
getName: function() {
return this.name;
},
getPrice: function() {
return this.price;
},
applyDiscount: function(discount) {
return this.price * discount;
}
}
객체 내부에서 해당 객체 프로퍼티에 접근하려면 this
키워드를 사용할 수 있음.
그런데, 새로운 차가 출시되어 객체를 추가해야 하는데, 프로퍼티는 똑같이 구성되어야 한다면
이럴 때, 차마다 객체를 늘려나가서 코드가 길어지는 것이 아니라, 필요한 정보를 담은 Car라는 클래스(class)를 생성하여 관리할 수 있음.
클래스 : 클래스는 반드시 정의(선언)한 뒤 사용 가능.
객체 설계도인 클래스는 문법이 비슷함.
가장 큰 차이는 constructor라는 생성자 함수
//클래스 선언
class Car {
constructor(name, price) {
this.name = name;
this.price = price;
this.department = "선릉지점";
this.salesAmount = 0;
}
applyDiscount(discount) {
return this.price * discount;
}
addSales() {
this.salesAmount++;
}
changeDepartment(departmentName) {
this.department = departmentName;
}
}
//클래스 사용
const morning = new Car('Morning', 2000000);
인스턴스화 : class로 객체 생성하는 과정
인스턴스 : class를 통해 생성된 객체
class의 property이름과 method를 갖는 객체. 인스턴스마다 모두 다른 프로퍼티 값을 갖고 있음.
class는 새로운 instance를 생성할 때마다 constructor() 메서드를 호출
Car는 class이름. 항상 대문자로 시작하고, CamelCase로 작성해야함.
Car class의 instance를 생성할때마다 constructor 메서드가 호출됨.
constructor() 메서드는 name, price 2개의 argument(인자)를 받음.
constructor() 메서드에 this 키워드를 사용. class의 실행범위(context)에서 this 는 해당 instance를 의미함.
constructor() 에서 인자로 넘어오는 name과 price를 사용해 Car instance의 name, price 프로퍼티에 값을 할당함.
이렇게 클래스 내에서 name, price와 같이 변경 가능한 상태값이자 class내의 컨텍스트에서 어느 곳에서나 사용할 수 있는 변수를 '멤버 변수'라고 부름.
멤버 변수는 this 키워드로 접근.
인스턴스 작성 규칙
인스턴스는 Class 이름에 new 를 붙여서 생성함.
클래스 이름 우측에 () 괄호를 열고 닫고, 내부에는 constructor 에서 필요한 정보를 인자로 넘겨줌.
Car클래스의 instance를 morning 이라는 변수에 저장했음.
다시 한 번! Car 클래스의 새로운 instance를 생성하려면 new 키워드가 필요함.
new 키워드는 constructor() 메서드를 호출하고 새로운 instance를 return해줌.
'Morning'이라는 String과 2000000 이라는 Number를 Car 생성자에 넘겨주었고, name, price 프로퍼티에 각자의 값이 할당됨.
메서드 : 함수. 객체가 프로퍼티 값으로 갖고 있는 것을 메서드라고 부름. Class의 method는 Object(객체)의 문법과 똑같음.
객체는 프로퍼티마다 comma(,)로 구분해줘야 했지만, 클래스는 그렇지 않음.
Assignment
class 생성을 연습해보겠습니다.
MyMath 라는 class를 생성해주세요.
constructor 에서는 숫자 2개를 인자로 받아 프로퍼티로 저장합니다.
총 4개의 메서드를 구현해주세요.
getNumber : 두 개의 숫자가 무엇인지 배열로 반환하는 메서드 → ex) [1, 2]
add : 두 개의 숫자를 더하는 메서드
substract : 두 개의 숫자를 빼는 메서드
multiply : 두 개의 숫자를 곱하는 메서드
class MyMath {
constructor(number1, number2) {
this.number1 = number1;
this.number2 = number2;
}
getNumber() {
let arr = [];
arr.push(this.number1);
arr.push(this.number2);
return arr;
}
add() {
return this.number1 + this.number2;
}
substract() {
return this.number1 - this.number2;
}
multiply() {
return this.number1 * this.number2;
}
}
module.exports = { MyMath };
object literal(객체 리터럴) : {} 으로 생긴 모양의 객체
객체 : 순서가 없는 데이터 모음
key ( property name ) : 특정 값 가진 변수 같은 역할.
프로퍼티에 어떤 값이 저장돼 있는지 알 수 있음.
value ( property value )
프로퍼티 접근법
dot notation : dot(.) 활용( 키로 바로 접근할 때 사용 )
bracket notation : []활용. 키 이름을 따옴표로 감싸서 작성해야 함. 변수 활용해서 키 접근 가능
숫자로 된 키, 띄어쓰기 된 키, 변수 사용시, -, ! 사용시
배열 : 순서가 있는 데이터 모음
let difficult = {
33: '숫자 형식도 되네',
'my name': '스페이스 포함 가능',
color: 'silver' ,
키: '한글인 키는 따옴표가 없어도 되는군!!',
'!키': '느낌표 있는 키는 따옴표가 필요하군',
$special: '$는 없어도 되는군',
'hey-yo': '이런 것도 따옴표 필요?'
};
console.log(difficult);
console.log(difficult.33);
console.log(difficult['my name']);
console.log(difficult.color);
console.log(difficult.키);
console.log(difficult['!키']);
console.log(difficult.$special);
console.log(difficult['hey-yo']);
프로퍼티 할당
difficult[name] = '값 바꾼다';
console.log(difficult[name]);
difficult.color = '색깔';
console.log(difficult.color);
console.log('생성전: ' + difficult.new);
difficult.new = '새로 추가된 프로퍼티';
console.log('생성후: ' + difficult.new);
객체에 이미 키가 존재하는데, 다시 한 번 할당하면 값이 교체(수정)됨
이전에 없던 키로 접근하면, 새로운 프로퍼티가 추가됨.
아직 없던 키에 접근하면 프로퍼티를 추가할 준비는 되어있지만, 값이 없음. (undefined출력됨)
없었던 키에 값을 바로 입력해서 프로퍼티를 추가하는 방법
difficult.realNewProperty = '추가 됐다';
const와 객체
const 로 선언된 변수에 객체를 다시 할당하면 오류가 생기지만, 그 객체에 프로퍼티를 추가하거나 수정하는 것은 가능함.
const mutableObj = {
name: '객체'
};
mutableObj = {
name: '수정'
}
메서드 : 객체에 저장된 값이 함수일 때, 메서드라고 부름.
console.log() 도 형태를 보니 객체. 자바스크립트 어디에나 접근이 가능 했으니 global 객체. console 다음에 dot(.)으로 프로퍼티를 접근했고, log 라는 키의 값은 함수. log는 console 이라는 객체의 메서드.
객체에 메서드 정의, 호출하는 방법
let methodObj = {
do: function() {
console.log('메서드 정의는 이렇게');
}
}
methodObj.do();
중첩 객체 ( Nested Object )
let nestedObj = {
type: {
year: '2019',
'comment-type': [{
name: 'simple'
}]
}
}
객체는 reference로 저장됨
객체를 변수에 저장하면 객체 자체가 저장되는 것이 아니라 객체가 담긴 어느 메모리 reference를 저장하기 때문
텍스트는 변수에 저장하면 텍스트 자체가 저장됨
서로 같은 텍스트 비교 연산하면 서로 값이 같아서 true
const a = '안녕';
const b = '안녕';
console.log(a === b);
아래의 객체는 생긴 모양이 아예 똑같은데 false 라고 출력
const hiObj = {
name: '안녕'
};
const helloObj = {
name: '안녕'
};
console.log('객체비교 =>', hiObj === helloObj);
const로 선언된 객체에 새로운 객체를 할당하면 오류 발생함.
새로운 메모리 주소(refernece)로 수정을 시도하기 때문
하지만, mutableObj.name 로 프로퍼티에 접근해서 수정할 수 있음. mutableObj 가 저장된 reference가 바뀌는 것이 아니라 객체 내부의 프로퍼티 값이 수정되는 것이라서 가능함.
Assignment
getAnswer 함수를 구현해 주세요.
getAnswer 함수는 아래의 객체에서 '샐러드' 라는 값을 출력합니다.
let myProfile = {
name: '김개발',
address: {
email: 'geabal@gmail.com',
home: '위워크'
},
'my favorite': {
food: [{
name: '샐러드',
price: 3500
}, {
name: '삼겹살',
price: 15000
}],
hobby: ['축구']
}
}
function getAnswer() {
return myProfile['my favorite'].food[0].name;
}
console.log(getAnswer());