[Achievement Goal]
객체 복습 (프로퍼티 추가 / 삭제 / 확인)
1. 클래스와 인스턴스의 용어를 이해한다.
👉 new / class
2. 객체지향 프로그래밍의 특징 네가지
👉 캡슐화 / 상속 / 추상화 / 다형성
3. 객체지향 프로그래밍에서의 상속
👉클래스 상속의 원리 이해
👉프로토타입 체인에 대한 이해.(__proto__)
기존 객체에 프로퍼티 추가하기
let person = {
name : 'sook',
age : 20,
}
person['city'] = 'NewYork' //city 추가.
person.hobby = ['pilates','tennis','watchingMovie'] //hobby 배열 추가
/*
'city' in person //true; (in 으로 불리언타입 리턴하여 확인.)
'hobby' in person // true;
*/
기존 객체에서 프로퍼티 삭제하기
let person = {
name : 'sook',
age : 20,
city : 'NewYork'
hobby : ['pilates','tennis','watchingMovie']
}
delete person['age'] //age 삭제하기
/*
'age' in person // false;
*/
*객체에서의 메소드/인스턴스 호출은 this 를 이용한다.
(singleTon / 클로저 두가지 방법으로 메소드 호출 가능.)
하나의 큰 설계도를 바탕으로 각각의 객체가 들어가 있는 형태이다.
여기서 설계도는 클래스의 역할을 하고 각각의 만들어진 객체는 인스턴스가 된다.
즉, 어떠한 주제가 되는 개념을 크게 잡고 그와 관련된 자잘한 객체주머니들을 생성한다고 생각하면 되겠다.
(ex- 해외여행(클래스) ->
{미국(지역,숙소,맛집)},{캐나다(지역,숙소,맛집)},{프랑스(지역,숙소,맛집)}(인스턴스))
클래스는 객체들을 담은 또 하나의 함수가 되고, 이 함수를 사용하는데 몇가지 규칙이 있다.
1. new 키워드 사용
2. 대문자 사용
3. 일반명사 사용
(2,3번은 optional 하지만 일반 함수와 구분하기 위해서라도 지켜주도록 한다.)
인스턴스가 초기화 될 때 실행하는 생성자 함수이며, 최신 자바스크립트 ES6 부터 도입 되었다.
일반적인 함수형태가 아닌 class 함수와 같이 쓰이며 return 값을 쓰는 대신 this 키워드를 사용하여 호출한다.
형태
class Travel{
constructor(city,hotel,restaurant){
// return 값이 필요 없다.
this.city = city;
this.hotel = hotel;
this.restaurant = restaurant;
}
rent(){ //메소드
}
tour(){ //메소드
}
}
let usa = new Travel('sanfranCisco','airBnB','Sotomare')
let canada = new Travel('vancouver','homestay','Barbara')
let france = new Travel('paris','hyatt hotel','Cavalier')
캐나다만 까보면 Travel 이라는 함수안에 해당 인스턴스 객체들이 담아져 있는것을 볼 수 있다.
usa.city // sanfranCisco;
usa.tour() // 미국에서 투어를 한다.
canada.hotel // homestay;
canada.rent() // 캐나다에서 렌트를 한다.
이렇게 new 키워드를 사용한 Travel 클래스함수를 각 변수에 담아두면 클래스 고유의 속성, 메소드를 가진 인스턴스가 만들어진다.
속성 : 명사
메소드 : 동사
100% 그렇다는 것은 아니지만 내머리로 이해하기엔 이게 제일 적합했다.
이 말이 무엇인고 하면, 속성은 현재 주어진 명확한 값으로 생각해 볼 수 있다.
만약 어떠한 학생의 정보가 있다고 치자.
학생의 속성은
{ 이름:'숙', 학교: 하버드 , 공부하는 과목:'수학' }
으로 나눌 수 있다.
메소드는 객체 함수를 도와주는 또하나의 함수이다.
이 학생의 메소드는
go(go to Univ driving her self) study(study math)
가 될 수 있다.
클래스는 사실 배열에서 빛을 발한다.
new Travel 로 우리가 만든 클래스 함수로 지정해 줄 수 있었다면,
new Array 라는 내장함수로 배열을 만들 수 있다.
let travel = new Array('usa','canada','france' )
travel.length; //3
travel.pop() // ['usa','canada']
단, new Array 로 배열을 정의할 때 인자로 올 수 있는것들은 인스턴스 이다.
oop 의 정의는 모든것을 "객체" 로 그룹화 한다는 것이며, 이 객체는 한 번 생성이 되면 메모리 내에서 반환되기 전 까지는 모든것이 유지 된다.
OOP 에는 대표적인 특징 네가지가 있다.
캡슐화 / 상속 / 추상화 / 다형성
캡슐화는 속성과 메소드를 따로 정의하는 것이 아니라, 한 객체 안에 묶어서 사용하는 특징을 말한다.
class Travel{
constructor(city,hotel,restaurant){
// return 값이 필요 없다.
this.city = city;
this.hotel = hotel;
this.restaurant = restaurant;
}
rent(){ //메소드
}
tour(){ //메소드
}
}
앞서 나타낸 예시 또한 캡슐화를 잘 보여주고 있다.
이는, 코드 실행 순서에 따라 작성하는것이 아닌!! 코드가 상징하는 모습, 스타일을 기준으로 결합을 한다.
속성과 메소드만을 보고 이 인스턴스가 어떠한 기능을 추구하는지 알 수 있게 해주는 특징이고 이를 "느슨한 결합(Loose Coupling) 이라고도 한다.
객체 내에서 메소드를 작성 할 때는 주의할 점이 있다.
추후 유지보수 시 코드의 흐름을 유지하기 위해서 객체 내 메소드만 조작 가능하도록 코드를 잘 짜는것이 중요하다. 필요없는 코드나 데이터를 은닉한다는 뜻에서 이를 코드의 은닉화 라고도 하는데 클래스를 위한 속성, 메소드 모아놨으니까 이 속성은 클래스 내의 메소드로만 변경 가능하게 하자, 정의한것.
인스턴스 B 메소드를 사용한다고 해서 인스턴스 A 속성이 변하지 않는다.
장점 : 코드의 간결성, 재사용성을 높인다.
우리가 흔히 알고있는 부모가 자식에게 물려주는 개념이다.
내용이 비슷한 객체를 여러번 써야한다면 매우 번거로울 것이다.
객체는 이를 보완하기 위한 상속이 가능하다.
어떠한 객체가 자식객체에게 그대로 물려주고, 그 자식객체는 물려받은 객체에 속성 또는 메소드를 필요한만큼 추가 할 수 있다.
장점 : 불필요한 코드를 줄여 재사용성을 높인다.
실제로 노출되는 부분은 아주 단순해 보이지만 내부 구현은 복잡한 개념을 말한다.
우리가 주변에서 쉽게 볼수있는 기계들이 대표적인 예시들이다.
우리가 사용할땐 아주 손쉽게 사용하지만 사실 그 안에는 수많은 전선과 복잡한 기능들이 내포되어있지 않은가?
사용자는 그 수많은 전선을 볼 필요 없이 필요한 기능만을 사용할 수 있는 인터페이스를 보며 사용한다. 개발자는 필요하지 않은 기능, 메소드를 숨기고 단순 이름으로만 정의하는것, 이것이 추상화 이다.
장점 : 코드의 간결성, 인터페이스의 단순화.
다양한 형태를 가질 수 있는 개념이다.
예를들어 말하다 에도 여러가지 영어단어들이 존재한다.
speak , tell , mention , say , talk ...
이 단어들은 똑같이 입으로 말하지만 어떻게 말하냐에 따라 조금씩 의미가 달라지는 것들이다. 객체 역시, 똑같은 메소드 이지만 다르게 구현 될 수 있다.
장점 : 동일한 메소드에 대해 객체의 특성에 맞게 달리 작성 가능. (if/else 불필요)
자바스크립트는 프로토타입 기반의 언어이다.
프로로타입은 시제품을 떠올리면 되는데, 아직 출시되지 않은 원형 객체를 말한다.
배열을 예로들어
.__propto__
new Array();
=>
.constructor
.prototype
프로토 타입에는 다양한 메소드가 존재한다.
let array = new Array(~~) 에서
prototype 은 slice , push , pop, map 등 배열 메소드라고 볼 수있다.
객체지향 특성 중 "상속" 특징을 구현할때 프로토타입을 사용한다.
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
study(){
}
eat(){
}
}
let sook = new Person('sook',20);
속성
sook.name //'sook'
sook.age // 20;
메소드
sook.study();
sook.eat();
extends 와 super 를 이용해 Person 객체를 상속해온 후 추가한다.
class Female extends Person{
constructor(name,age,city,hobby){
super(name,age)
//this.name=name, this.age=age 로 쓸 수 있지만 중복되므로,
//코드의 간결성을 위해 super 를 사용한다.
this.city = city;
this.hobby = hobby;
}
study(){
}
eat(){
}
}
let jully = new Female('seoul','coding');
jully.city // 'seoul'
jully.hobby // 'coding'
document.createElement('div') 로 div 를 생성할 수 있다.
이때 생성된 div 는 HTMLDivElement 라는 클래스의 인스턴스 이다.
class HTMLDivElement{
constructor(~~){
this.~~ = ~~
}
}
let div = document.createElement('div')
모든 DOM 요소들은 속성 및 메소드를 가지고 있는데 이는 Element 라는 공통부모 클래스가 있다는 것을 알 수 있다.
최종부모부터 자식까지의 구조를 보면 다음과 같다.
EventTarget -> Node -> Element -> HTMLElement ->HTMLDivElement
🤔 고민해보기
addEventListener 어떤 클래스의 프로토타입에서 찾을 수 있을까?
remove 메소드는 어떤 클래스의 프로토타입에서 찾을수 있을까?
모든 객체에 toString() 메소드가 존재하는 이유는?