객체 지향 프로그래밍이란?
: 하나의 모델이 되는 청사진을 만들고, => class
그 청사진을 바탕으로 한 객체를 만드는 프로그래밍 패턴 => instance
객체지향 프로그래밍은 현실 세계를 기반으로 프로그래밍 모델을 만들때 유리하다!
객체는 일반적인 함수를 정의하듯 만든다.
이 때, new
키워드를 사용한다.(새로운 인스턴스를 만드는 방법)
클래스는 보통 대문자로 시작해 일반명사로 만든다(다른 함수와 구분하기 위함)
클래스에 속성과 메소드를 정의하고, 인스턴스에서 이용한다.
ES5
function Car(brand, name, color) {
this.brand = brand;
this.name = name;
this.color = color;
}
ES6
class Car {
constructor(brand, name, color) {
this.brand = brand;
this.name = name;
this. color = color;
this
= 한마디로 인스턴스 객체
= parameter로 넘어온 브랜드, 이름, 색상 등은 instance 생성시 지정하는 값이며,
위와 같이 this에 할당한다는 것은 만들어진 인스턴스에 해당 브랜드, 이름, 색상을 부여하겠다는 의미
ES5
function Car(brand, name, color) { /* 생략 */ }
Car.prototype.refuel = function() {
// 연료 공급을 구현하는 코드
}
Car.prototype.drive = function() {
// 운전을 구현하는 코드
}
ES6
class Car {
constructor(brand, name, color) { /* 생략 */}
refuel() {
}
drive() {
}
}
prototype
= 모델의 청사진을 만들 때 쓰는 원형 객체(original form)
constructor
= 인스턴스가 초기화될 때 실행하는 생성자 함수
this
= 함수가 실행될 때, 해당 scope마다 생성되는 고유한 실행 context(execution context) new 키워드로 인스턴스를 생성했을 때에는, 해당 인스턴스가 바로 this의 값이 됨
ES5
function Car(brand, name, color) {
this.brand = brand;
this.name = name;
this.color = color;
}
Car.prototype.drive = function() {
console.log(this.name + '가 운전을 시작합니다')
}
let avante = new Car('hyndai', 'avante', 'black');
avante.color; // 'black'
avante.drive(); // 'avante가 운전을 시작합니다'
ES6
로 변경하면
class Car {
constructor(brand, name, color) {
this.brand = brand;
this.name = name;
this.color = color;
}
drive() {
console.log(this.name + '가 운전을 시작합니다')
}
절차적 언어(과거)
객체 지향 언어
OOP
클래스와 인스턴스
캡슐화: 코드가 복잡하지 않게 만들고, 재사용성을 높인다.
추상화: 코드가 복잡하지 않게 만들고, 단순화된 사용으로 변화에 대한 영향을 최소화한다.
상속: 불필요한 코드를 줄여 재사용성을 높인다.
다형성: 동일한 메서드에 대해 if/else if와 같은 조건문 대신 객체의 특성에 맞게 달리 작성하는 것이 가능해진다.
코드 상에서, 혹은 화면에 보이는 하나의 요소를 객체 단위로 구분시켜서 생각하면, 보다 이해하기 쉬운 코드를 작성할 수 있게 된다. OOP의 특성을 이해하고 잘 사용하면 좋은 설계를 할 수 있다.
= 모델의 청사진을 만들 때 쓰는 원형 객체(original form)
= 일종의 유전자
ex)
부모.prototype.name = 'kim'
자식.name // "kim"
부모에 직접 쓰면 자식이 직접 가지지만
유전자에 쓰면 부모만 {name:'kim'} 가진다.(자식이 끌어다 쓴다)
따라서 상속을 하고 싶으면 prototype을 사용!
부모 유전자에 있는걸 자식이 사용 가능한 이유는 뭘까?
Javascript에서 자식.name을 조회할때
nunu가 name을 가지고 있지 않으면 -> nunu 부모유전자를 뒤진다
<object에서 자료 뽑을 때 일어나는 일>
1. 직접 자료를 가지고 있으면 그거 출력
2. 없으면 부모유전자까지 뒤짐
3. 없으면 부모의 부모 유전자까지....없을때까지 계속함
prototype 객체는 기본적인 속성으로 constructor와 proto 를 가지고 있다
이중 proto 에는 자식의 부모 prototype 객체를 가리키는 링크를 담고 있다
__proto__
를 이용하면 부모 클래스의 프로토타입, 혹은 '부모의 부모 클래스'의 프로토타입을 탐색할 수 있음.
Object = 가장 상위 객체(모든 객체의 부모격) 따라서 모든 프로토타입 chain의 종점은 Object.prototype
let div = document.createElement('div');
div.__proto__ // HTMLDivElement
div.__proto__.__proto__ // HTMLElement
div.__proto__.__proto__.__proto__ // Element
div.__proto__.__proto__.__proto__.__proto__ // Node
div.__proto__.__proto__.__proto__.__proto__.__proto__ // EventTarget
div.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__ // object
div.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__ // null
프로토타입 종착지는 null
이러한 체인의 특징으로 현재 객체에 특정 속성이나 메서드가 없더라도, 체인으로 연결된 부모 객체에 있는 속성이나 메서드를 사용할 수 있음.