저번 달에 객체지향, 프로토타입을 파다 이해가 어려워 포기한 적이 있다. 그래서 이번 수업에 잔뜩 겁을 먹고 있었다. 하지만 다시 보니 단어도 친숙해져 있고 눈에 들어오지 않았던 것이 보여 이해하는 데 성공했다!!! 역시 예습이 답이라고 생각했다. 내일 내용도 미리 보기 위해 Unit3에 들어가 보았다. ...비동기? 하나도 모르겠다. 산 넘어 산이다. 내일도 열심히 머리를 굴려봐야겠다.
Unit2 - JavaScript 객체 지향 프로그래밍
Chapter1. 객체 지향
-1. 클로저 모듈 패턴
-2. 클래스와 인스턴스
-3. 객체 지향 프로그래밍
-4. 객체 지향 차이점
Chapter2. Prototype
-1. 프로토타입과 클래스
-2. 프로토타입 체인
1. 클로저 모듈 패턴
1) 객체 지향 프로그래밍(OOP, Object-oriented programming)
절차 지향 프로그래밍과는 다르게 데이터와 기능을 한 곳에 묶어서 처리
주의. 객체지향이 무조건 좋은 것은 아님
메모리 관리가 중요하다면? -> 메모리를 적게 쓰는 절차 지향
사람들과의 협업이 중요하다면? -> 코드 이해가 쉬운 객체 지향
2) 메서드 호출 방식 이용 시 화살표 함수를 사용 불가
참고. 화살표 함수의 제한점
this나 super에 대한 바인딩이 없고, methods로 사용될 수 없음
new.target 키워드에 접근 불가
일반적으로 스코프를 지정할 때 사용하는 call, apply, bind methods를 이용할 수 없음
생성자(Constructor)로 사용할 수 없음
yield를 화살표 함수 내부에서 사용할 수 없음
3) 클로저 모듈 패턴 사용 이유 -> 재사용을 위해
똑같은 기능을 하는 인스턴스 객체를 여러 개 만들어 재사용할 수 있음
2. 클래스와 인스턴스
1)
class -> 자동차 청사진
instance -> 청사진을 바탕으로 한 객체(객체 안에 포함되는 개념)
출처:http://www.w3big.com/ko/php/php-oop.html#gsc.tab=0
2) 새로운 인스턴스를 만드는 법: new
클래스는 인스턴스를 찍어냄
참고.
class 이름: 대문자 시작, 일반명사
일반적인 함수 이름: 소문자 시작, 동사 포함
3) 클래스를 만드는 법: 함수로 정의(es5), class(es6)
//ES5: 함수로 정의
//function이 생성자 함수
function Car(brand, name, color) {
// 인스턴스가 만들어질 때 실행되는 코드
}
//ES6: class 이용해 정의
class Car {
//constructor가 생성자 함수
constructor(brand, name, color) {
// 인스턴스가 만들어질 때 실행되는 코드
}
}
참고. 생성자 함수 특징
함수 이름의 첫 글자는 대문자로 시작
반드시 'new' 연산자를 붙여 실행
4) 인스턴스 만드는 법: new 키워드
let avante = new Car('hyundai', 'avante', 'black');
let mini = new Car('bmw', 'mini', 'white');
let beetles = new Car('volkswangen', 'beetles', 'red');
new가 사용되면
-> 생성자 함수 실행
-> 변수(avante, mini, beetles)에 인스턴스 할당
-> 클래스(Car)의 고유 속성과 메소드 가짐
5) 속성과 메소드
클래스 -> 속성, 메소드 정의
인스턴스 -> 속성, 메소드 이용
자동차 예시.
속성: 브랜드, 차 이름, 색상, 현재 연료 상태, 최고 속력 등
메소드(객체에 딸린 함수): 연료 주입, 속력 설정, 운전 등
6) 속성을 정의하는 법: this 이용
//ES5
function Car(brand, name, color) {
this.brand = brand; // 인스턴스의 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: 인스턴스 객체를 의미
this에 할당한다는 것: 만들어진 인스턴스에 해당 브랜드, 이름, 색상을 부여하겠다는 의미
참고.
7) 메소드를 정의하는 법: 함수 밖에서 prototype(es5), 함수 안에 삽입(es6)
// ES5: 함수 밖, prototype 이용
function Car(brand, name, color) { /* 생략 */ }
Car.prototype.refuel = function () {
// 연료 공급을 구현하는 코드
}
Car.prototype.drive = function() {
// 운전을 구현하는 코드
}
// ES6: 함수 안
class Car(brand, name, color) {
constructor(brand, name, color) { /* 생략 */ }
refuel() {
// 연료 공급을 구현하는 코드
}
drive() {
// 운전을 구현하는 코드
}
}
참고. constructor도 메서드
class로 생성된 객체를 생성하고 초기화하기 위한 특수한 메서드
return 없음
클래스 안에 한 개만 존재할 수 있음
8) 인스턴스에서 속성, 메소드 사용법
class Car {
constructor(brand, name, color) {
this.brand = brand;
this.name = name;
this.color = color;
}
refuel() {
console.log(this.name + '에 연료를 공급합니다');
}
drive() {
console.log(this.name + '가 운전을 시작합니다');
}
}
let avante = new Car('hyundai', 'avante', 'black');
console.log(avante.color); //black
console.log(avante.refuel()); //avante에 연료를 공급합니다
9) JavaScript에서만 유효한 용어 사전
10)
참고. 프로토타입 메소드, 정적 메소드
class 안에 정의된 메소드는 프로토타입 메소드 ---> 인스턴스에서 호출
앞에 static을 붙이면 정적 메소드 ---> 클래스에서 호출
11) 배열 정의 = Array라는 클래스의 instance를 만드는 것
// 자동차 예시
let avante = new Car('hyundai', 'avante', 'black');
avante.color;// 'black'
avante.drive();// 아반떼가 운전을 시작합니다
// 평소 배열 정의
let arr = ['code', 'states', 'pre'];
arr.length;// 3
arr.push('course');// 새 element를 추가합니다
// 사실은 배열 정의도 클래스의 인스턴스 생성
// class: Array
// instance: arr
// length, push: Array prototype object의 메소드
let arr = new Array('code', 'states', 'pre');
arr.length;// 3
arr.push('course');// 새 element를 추가합니다
지금까지 만들었던 배열: class Array의 instance object
length, push -> class Array의 prototype에 정의된 메소드
12) 실습
class Counter {
constructor() {
//왜 파라미터가 없지: 인스턴스 생성 시 지정하는 값이 필요 없으므로
this.value = 0; //this는 Counter가 아닌 counter1을 가리킴
}
increase() {
this.value++;
}
decrease() {
this.value--;
}
getValue() {
return this.value; //왜 여기만 return 있지
}
}
let counter1 = new Counter();
counter1.increase();
counter1.increase();
console.log(counter1.getValue()); //2
3. 객체 지향 프로그래밍
1) 객체 지향 프로그래밍 이전
절차 지향 프로그래밍 존재
절차적 언어는 순차적인 명령의 조합
2) 객체 지향 프로그래밍 등장
데이터(속성)와 기능(메소드)을 별개로 취급하지 않고, 한 번에 묶어서 처리
(속성과 메소드가 같이 클래스에서 정의됨)
3) OOP(Object Oriented Programming)
프로그램 설계 철학
모든 것을 '객체'로 그룹화
재사용성(캡슐화, 추상화, 상속화, 다형성을 통해 얻을 수 있음)
4) 클래스와 인스턴스
5) OOP Basic Concepts
-Encapsulation(캡슐화)
속성과 메서드를 하나의 객체 안에 넣어 묶음
실제 구현 내용 일부를 내부에 감추어 은닉 -> 유지보수, 수정 용이
느슨한 결합 -> 불필요한 코드 변경 줄임, 재사용성 높임
-Inheritance(상속)
부모 클래스의 특징을 자식 클래스가 물려받는 것
기본 클래스(base class)의 특징을 파생 클래스(derived class)가 상속 받음
-> 코드 중복 줄임
-Abstraction(추상화)
내부 구현은 아주 복잡한데, 실제로 노출되는 부분은 단순하게 만듦
->인터페이스가 단순
->너무 많은 기능들이 노출되지 않은 덕분에 예기치 못한 사용상의 변화가 일어나지 않도록 만들 수 있음
-Polymorphism(다형성)
같은 메서드라 하더라도, 다른 방식으로 구현될 수 있음
ex. render() 메서드는 TextBox, Select, CheckBox에서 다르게 렌더링
참고. 캡슐화, 추상화
캡슐화 예시 -> 클래스에 속성과 메소드를 같이 담는 것
추상화 예시 -> 클래스에 이름을 설정하는 것
참고 사이트(캡슐화): https://bperhaps.tistory.com/entry/%EC%BA%A1%EC%8A%90%ED%99%94%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-%EC%96%B4%EB%96%A4-%EC%9D%B4%EC%A0%90%EC%9D%B4-%EC%9E%88%EB%8A%94%EA%B0%80
참고 사이트(느슨한 결합): https://taesan94.tistory.com/85
4. 객체 지향 차이점
1) javascript는 private, interface 키워드 없음(TypeScript에 존재)
prive -> 은닉화 관련
interface -> 추상화 관련
1. 프로토타입과 클래스
1) 인스턴스, 생성자 함수, 프로토타입 객체, Object Prototype Object, function Object() {}의 관계
-객체는 언제나 함수로부터 나옴
-함수를 정의하면 함수와 함수의 프로토타입 객체가 생성
-prototype
: 함수에 존재, 프로토타입 객체를 가리킴
-constructor
: 프로토타입 객체에 존재, 함수를 가리킴
-__proto__
: 모든 객체(인스턴스, 프로토타입 객체)에 존재, 객체가 생성될 때 조상이었던 함수의 Prototype Object를 가리킴
참고자료(프로토타입): https://medium.com/@bluesh55/javascript-prototype-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-f8e67c286b67
2. 프로토타입 체인
1) extends, super
-extends
class 자식클래스 extends 부모클래스
: 클래스를 다른 클래스의 자식으로 만들기 위해 class 선언 또는 class 식에 사용
-super()
constructor 안에서 super(물려받을 속성)
: 부모 클래스의 생성자 호출, super()의 매개변수를 통해 상위 클래스의 멤버를 상속받을 수 있음. this 전에 써주어야 함, 한 번만 사용될 수 있음.
constructor 밖에서 super.부모 클래스 함수
: 부모 클래스 함수에 접근
//부모 클래스
class Person {
constructor(first, last, age, gender, interests) {
this.name = {
first,
last
};
this.age = age;
this.gender = gender;
this.interests = interests;
}
greeting() {
console.log(`Hi! I'm ${this.name.first}`);
};
farewell() {
console.log(`${this.name.first} has left the building. Bye for now!`);
};
}
//자식 클래스
class Teacher extends Person {
constructor(first, last, age, gender, interests, subject, grade) {
super(first, last, age, gender, interests);
// subject and grade are specific to Teacher
this.subject = subject;
this.grade = grade;
}
}
//결과: 상속 가능
let snape = new Teacher('Severus', 'Snape', 58, 'male', ['Potions'], 'Dark arts', 5);
snape.greeting(); // Hi! I'm Severus.
snape.farewell(); // Severus has left the building. Bye for now.
snape.age // 58
snape.subject; // Dark arts
주의.
constructor 안의 속성, constructor 밖의 매소드 모두 Person.prototype에 저장됨
2) DOM에서 div와 프로토타입
-div 엘리먼트의 상속 관계
Object <- EventTarget <- Node <- Element <- HTMLElement <- HTMLDivElement <- div
__proto__
가 6개 붙은 것은 Object.prototype(Object 함수의 프로토타입 객체) 나옴
3) 프로토타입 체인
주의.
-함수.prototype
은 함수의 상위를 가리키는 것이 아님(생성자 함수와 함수의 프로토타입 객체는 동등)
-하위 클래스와 인스턴스는 다른 개념
생성자함수.prototype
-> 자신의 프로토타입 객체(동등)
객체.__proto__
-> 인스턴스라면 본인의 조상 함수의 프로토타입 객체, 프로토타입 객체라면 상위 클래스의 프로토타입 객체 의미(상위, 프로토타입 체인과 관련)