이전에 객체지향 class 생성자 함수를 공부했다.
class를 통한 instance생성에 낭비를 개선할 수 있는 prototype
상속기능을 요상하게(?)사용할 수 있게 하는 prototype
오늘은 이 prototype에 대해서 알아보기로 했다.
| keywords |
Prototype
Prototype Based Lanuange
javascript는 "프로토타입 기반 객체지향 프로그래밍"이다.
> 함수 is 객체
> 고로 생성자 함수 is 객체
> 객체는 뭘 가진다? property!
여기서 용도가 미리 약속된 특수한 프로퍼티를 prototype이라고 한다.
✅prototype의 필요성
/* 생성자 함수 */
function Cat(name, color, weight){
this.name = name;
this.color=color;
this.weight=weight;
this.intro = function(){
return this.name + "는 " + this.color + "색 이고 " + this.weight
}
}
var coco = new Cat('코코', '노랑', '4kg');
var mimi = new Cat('미미', '회색', '2kg');
console.log(coco.intro()); // 코코는 노랑색 이고 4kg
console.log(mimi.intro()); // 미미는 회색색 이고 2kg
- 위 코드에서 새로운 객체가 생성될 때마다 intro라는 함수가 새로 만들어진다.
- 이렇게 되면 시간과 메모리가 낭비되어 성능이 저하된다.
🤔만약 intance들의 intro함수의 내용을 바꾸고 싶다면?
var coco = new Cat('코코', '노랑', '4kg');
coco.intro = function(){
return "수정 : " + (this.name + "는 " + this.color + "색 이고 " + this.weight)
}
var mimi = new Cat('미미', '회색', '2kg');
mimi.intro = function(){
return "수정 : " + (this.name + "는 " + this.color + "색 이고 " + this.weight)
}
console.log(coco.intro()); // 수정 : 코코는 노랑색 이고 4kg
console.log(mimi.intro()); // 수정 : 미미는 회색색 이고 2kg
이렇게 각 객체마다 intro 함수를 수정해줘야한다.
생성자 안에서 intro함수와 같은 메서드를 가지는 것은 생산성이 떨어진다.
생성자 함수Cat를 통해 나오는 객체가 공통적으로 사용할 수 있는 함수나 속성을 만들 수있다면 좋은 해결책이 될 것이다.
이런 비효율을 개선할 수 있는 방법이 prototype개념이다.
prototype 프로퍼티로 함수를 생성하면 instance별로 함수를 생성하지 않아도 된다.
✅ prototype
function Cat(){}; // 이것은 객체.
var Person = new Function(); // 1번줄의 코드와 똑같은 의미. 즉 함수도 객체임.
즉 js의 함수들은 객체이기 때문에 property를 가질 수 있다.
예)
function Cat(name, color, weight){
this.name = name;
this.color=color;
this.weight=weight;
}
1.
Cat 함수를 생성하면 Cat객체와 Cat의 prototype객체가 생성된다.
✔️prototype을 '유전자'라고 이해하면 비유가 쉬움
2.
Cat객체의 내부에는 prototype이라고하는 프로퍼티가 생긴다.
그 프로퍼티는 Cat의 prototype객체를 가리킨다.
즉 Cat.prototype이라고 하면 prototype 객체를 가르키는 것.
3.
Cat의 prototype객체역시 construct라는 프로퍼티를 통해 Cat의 소속임을 표시한다.
서로간의 상호참조가 일어나는 것.
// prototype객체에 intro라는 프로퍼티를 생성한 후 함수를 정의
Cat.prototype.intro = function(){
return this.name + "는 " + this.color + "색 이고 " + this.weight
}
// 새로운 coco객체 생성
var coco = new Cat();
console.log(coco)
새로운 객체 coco만 호출하면, intro는 나오지 않는다
하지만 prototype 이라는 공간에서 intro함수를 가진 다는 것을 알 수 있다.
그래서 새로운 객체 coco에 intro를 호출하면 prototype에 선언한 intro함수에 접근할 수 있다.
✨ class에 프로퍼티를 선언한 것과 차이점
∙ class생성자 함수에 직접 intro함수를 사용 : class를 통해 생성된 모든 자식 객체가 intro함수를 직접가진다.
∙ prototype프로퍼티를 통해 intro함수를 생성 : 부모만 intro함수를 가짐
4.
✅ __proto__
var coco = new Cat('코코', '노랑', '4kg');
var mimi = new Cat('미미', '회색', '2kg');
coco객체를 생성하면 Cat 생성자 함수를 통해 프로퍼티들이 생성된다.
그리고 Cat객체의 prototype을 가리키는 __proto__라는 프로퍼티를 볼 수 있다.
// 두 방법 모드 Cat의 prototype에 접근할 수 있다.
Cat.prototype
coco.__proto__
5.
coco의 프로퍼티에 없는 coco.intro를 선택하면, __proto__를 타고 올라가 뒤져 Cat객체의 prototype에서 intro를 찾아내서 사용한다.
쩜인트로군 : coco야 너 intro있니?
coco냥 : 없는데요.
쩜인트로군 : 그럼 coco 부모님 유전자 좀 확인해볼게
✅ prototpye chain
❓여기서 coco의 부모님도 intro유전자가 없으면?
∙ 그 부모의 부모, 그 부모의 부모, 그 부모의 부모 .... 단군 할아버지한테까지 찾아감
이런 연쇄적인 참조를 portotype chain이라고 한다.
// coco의 부모의 부모의 부모
function GrandParentsCat(){}
GrandParentsCat.prototype.myLittleBoy = 'i love you❤︎';
// coco의 부모의 부모
function ParentsCat(){}
ParentsCat.prototype = new GrandParentsCat();
// coco의 부모
function Cat(){}
Cat.prototype = new ParentsCat();
// 나는 coco
var coco = new Cat();
console.log(coco.myLittleBoy); // i love you❤︎
✅ 이제 거대한 js의 일부분이 이해되기 시작한다.
배열을 하나 생성해보았다.
var Array = [3, 7, 9 ,2]
Array.sort(); // 2, 3, 7, 9
Array.length; // 4
❓우리가 Array라는 객체에 sort()나 length같은 함수를 추가해준 적이 있었나?
❌없음
배열을 new Array를 통해서 다시 만들어 보자.
var Array = [3, 7, 9 ,2]; // 인간 방식
var Array = new Array(3, 7, 9 ,2); // 컴퓨터 방식
작성 방식은 다르지만, 두 개는 똑같이 배열을 생성하게 된다.
여기서
var 변수 = new 생성자함수명();
어디서 많이 보지 않았나?
❗️결국 Array자체도 거대한 생성자 함수이다.
Array 함수 기능 : 원하는 값을 넣으면 배열로 만들어 줌.
❓우리가 메서드라 칭하는 sort()나 length같은 것을 사용할 수 있는 이유?
❗️이런 함수들이 부모 유전자(prototype)에 이미 기록되있어서
Array.prototype을 console에서 확인해보면 이미 만들어진 함수를 우리가 가져다 쓰는 것
❗️메서드를 검색할 때마다 이렇게 .prototype이 붙는 이유를 알아냄😏
이말인 즉,
Array.prototype.함수 = function(){} 이렇게 작성하면, 모든 Array자료에서 사용할 수 있는 나만의 함수를 만들수 있다는 것!
📚참고 자료
- 유튜브 "코딩애플" - "prototype 문법 10분만에 이해시켜줌"
- 유튜브 "생활 코딩" - "JavaScript 객체 지향 프로그래밍 - 15. prototype vs proto"
- 사이트 opentutorials : https://opentutorials.org/module/4047/24610
- 유튜브 "ZeroCho TV" - "ZeroCho의 JS 중급 강좌 11-9. 프로토타입을 쓰는 이유"
'D.evelop > JavaScript' 카테고리의 다른 글
[JavaScript] Ajax, Axios를 사용한 요청 (0) | 2021.11.22 |
---|---|
[JavaScript] fetch함수에서의 에러(Error) 처리 (0) | 2021.11.22 |
[TIL]Javascript - 객체지향 class (ES5/ES6) (1) | 2021.08.28 |
[TIL]Javascript - 전역 객체를 바인딩 하는 this (0) | 2021.08.22 |
[TIL]Javascript - 객체 접근 Dot Notation, Bracket Notation (0) | 2021.08.22 |
댓글