Intro
자바스크립트를 공부하다 보면 한번씩 만나거나 mdn 문서를 보더라도 자주 만나는 개념이다 !
array 에 대해서만 mdn 에서 보더라도 prototype이 찍혀있다 !
객체지향 프로그래밍
프로토 타입에 들어가기 앞서서 객체지향 프로그래밍에 대한 개념에 대해 정리를 하면 좋은데 ,
객체의 집합으로 프로그램을 표현하는 프로그래밍 패러다임 이다.
객체는 각각 속성(프로퍼티)을 가지고 있기 때문에 다른 객체와 구별 해서 인식 할 수 있다.
예를 들어 홍길동 이란 사람은 키가 180 이며 몸무게가 78kg 서울 롯데 시그니엘 아파트 3001호 산다. 라고 하면
이 홍길동이란 사람의 속성을 이용해서 다른 사람들과 구별 할 수 있는 것 입니다.
즉 객체지향 프로그래밍은 객체의 상태를 나타내는 데이터와 , 이 데이터를 조작할 수 있는 동작을 하나의 논리적인 단위로 묶은 것 이다.
사실 이게 말만 들으면 어려워서 .... ㅎㅎ
코드를 보면서 설명해 보겠다.
const hwanmin = {
name: 'hwanmin',
address: '광주 아무개 아파트',
homeIn: function () {
return `${this.name}이는 ${this.address}에 들어옵니다.`;
},
homeOut: function () {
return `${this.name}이는 ${this.address}에 나갑니다.`;
},
};
console.log(hwanmin.homeOut()); // hwanmin이는 광주 아무개 아파트에 나갑니다.
console.log(hwanmin.homeIn()); // hwanmin이는 광주 아무개 아파트에 들어옵니다.
즉 hwanmin 이라는 객체 상태 데이터인 name , address 를 사용해서 동작을 나타내는 하나의 논리적인 단위로 묶은 복합적인 자료구조 이다.
prototype 상속
상속은 객체지향 프로그래밍 핵심 개념이다 !!
즉 부모 클래스 상태 , 메서드 등을 그대로 상속 받아서 사용 가능한것 !!
상속을 이용하면 불필요한 코드 중복을 제거할 수 있습니다 !
아래 예제에서 생성자 함수가 있다고 가정해 보겠습니다 .
<중복 발생!!>
function Human(name) {
this.name = name;
this.getName = function () {
return `이름은 ${this.name} 입니다.`;
};
}
const HwanMin = new Human('hwamin');
const Andrew = new Human('Andrew');
console.log(HwanMin.getName());
console.log(Andrew.getName());
위 함수는 치명적인 문제가 있습니다.
HwanMin , Andrew 둘다 동일한 getName() 메서드를 포함하고 있습니다.
즉 불필요한 메서드 중복이 발생한 것 입니다.
이러한 중복 을 피하기 위해서 protoype 개념이 필요해 집니다.
<중복제거!!>
function Human(name) {
this.name = name;
}
Human.prototype.getName = function () {
return `이름은 ${this.name} 입니다.`;
};
const HwanMin = new Human('hwamin');
const Andrew = new Human('Andrew');
console.log(HwanMin.getName());
console.log(Andrew.getName());
즉 Human 생성자 함수로 생성한 모든 인스턴스는 Human.prototype의 모든 프로퍼티와 메서드를 상속 받는다!!
그 이후에 인스턴스들은 Human.prototype 에 있는 메서드에 접근이 가능해 집니다 .
프로토타입 객체
prototype이 존재하는 이유는 객체간 상속을 구현하기 위해서 사용 됩니다.
생성자 함수는 prototype 속성을 갖고 있고 , 만들어진 생성자함수.prototype은 constructor를 가지고 있다.
function Human(name) {
this.name = name;
}
Human.prototype.getName = function () {
return `이름은 ${this.name} 입니다.`;
};
console.log(Human.prototype.constructor); // [Function: Human]
constructor를 사용해서 생성자 함수에 접근할 수 있다 !
모든 객체는 -> __proto__ 접근자 프로퍼티를 사용해서 생성자함수.prototype 에 접근할 수 있다.
let hwanmin = {
name: 'hwammin',
};
console.log(hwanmin.hasOwnProperty('__proto__')); //false
console.log(Object.prototype.hasOwnProperty('__proto__')); //true
위 예시를 보면 객체가 직접 __proto__ 접근자 프로퍼티를 얻는게 아니라 , Object.prototype의 프로퍼티를 얻는 것 이다.
정리
__proto__ 접근자 프로퍼티 : Object.prototype을 상속받은 모든 객체가 가진다.
prototype 프로퍼티 : 생성자 함수 프로퍼티는 생성자함수.prototype 의 constructor를 가르킨다.
function Person(name) {
this.name = name;
}
const me = new Person('Hwan');
console.log(Person.prototype === me.__proto__); //true
console.log(me.constructor === Person); // true
즉 true 가 나오는 이유는 me.__proto__ 접근자 프로퍼티로 Person.prototype에 접근 했기 때문이다.
me.constructor === Person인 이유는 처음에 me 인스턴스가 생성될 때 Person.prototype을 상속 받는데 ,
이때 Person.prototype 은 constructor 로 생성자 함수를 가르킨 채로 상속되기 때문에 두번째 true가 나오는 이유이다.
📌 요약
1. 생성자 함수를 만들면 생성자함수.prototype 객체가 생성되고 , 이 객체는 constructor 로 생성자 함수를 가르킨다.
2. 생성자 함수를 이용해서 인스턴스를 만들면 __proto__ 접근자 프로퍼티로 생성자함수.prototype에 접근이 가능하다.
3. prototype 객체는 자식 인스턴스에 상속이 일어난다. 그래서 자식 instance 에서 constructor 를 사용하면 생성자 함수를 가르키는걸 확인 할 수 잇다.
그래서 mdn에 있는 Array.prototype.length 는 Array 를 상속받는 모든 인스턴스가 사용 가능한게 되는 것 이다.
🌟 Bonus (Super Array) 만들기
1. 제일 긴 글자 길이를 반환해주는 maxLength() 메서드 만들기 !
2. 중복된 배열 요소를 제거해준 removeOverlap() 메서드 만들기 !
class SuperArray extends Array {
maxLength() {
let max = this[0];
for (let i = 1; i < this.length; i++) {
if (max.length < this[i].length) {
max = this[i];
}
}
return max.length;
}
removeOverlap() {
let set = new Set(this);
return new Array(...set);
}
}
const superArray = new SuperArray(
'HwanMin',
'HwanMin',
'SuperHwanMin',
'안녕하세요반갑습니다ㅎㅎ!!!!'
);
console.log(superArray.maxLength()); 16
console.log(superArray.removeOverlap());[ 'HwanMin', 'SuperHwanMin', '안녕하세요반갑습니다ㅎㅎ!!!!' ]
각각 요소들은 부모 클래스인 Array를 상속받아서 만들었습니다.
부모 요소를 상속받은 SuperArray 클래스는 Array의 모든 메서드를 가져다 쓸 수 있고 ,
추가적으로 커스텀으로 만든 메서드 사용이 가능해 집니다 ! ! 🛠
'FrontEnd > JavaScript' 카테고리의 다른 글
[JS] Scope 스코프 with(deep dive) (0) | 2022.06.06 |
---|---|
[JS] 비동기 예제를 직접 만들면서 공부 (0) | 2022.05.29 |
[JS] Shallow Copy Deep Copy (0) | 2022.05.16 |
[JavaScript] Set 개념에 대해 알아보기 ! (0) | 2022.04.30 |
[JavaScript] 배열 APIs (0) | 2022.04.03 |