본문 바로가기

Study/JavaScript

[JavaScript] 객체지향2. Prototype = 유전자

#0. Prototype

- prototype은 construnctor를 만들면 자동으로 생성되는 공간이다.

- 이 안에는 constructor에 대한 정보들이 담기는데, 다음 사진과 같은 정보들이 담긴다.

- 저들은 대대로 전해져 오는 나의 유전자라고 생각하자. 

constructor 대충 만들어서 prototype이 있는지 콘솔에 쳐봤음.

 

* constructor를 모른다면? 아래 글 먼저 읽어보세요

 

- constructor만 생성하면 prototype이 정말 생성되는지 확인해보자.

- 진짜 constructor만 생성하고 나는 저기 this.prototype같은거 추가안해줬는데, 뭐가 출력이 된다.

// 1. Constructor 생성
function Student(name, age) {
    this.name = name; 
    this.age = age;
    this.sayHi = function(){
    	console.log(`안녕하세요 ${this.name} 입니다`); 
    }
}

// 2. 나는 따로 prototype이란걸 생성하지 않았는디.. 이렇게 치면 뭐가 나오네..?
Student.prototype  // 출력결과 >> {constructor: ƒ}

저 student.prototype에 담겨있는 정보들..

 

- prototype 은 대대손손 물려받는 우리집안의 특징적인 유전자와 같은 거라, prototype에 값을 추가하면 모든 자식들이 물려받을 수 있다.

// 1. Constructor 생성
function Student(name, age) {
    this.name = name; 
    this.age = age;
    this.sayHi = function(){
    	console.log(`안녕하세요 ${this.name} 입니다`); 
    }
}

// 2. 나는 따로 prototype이란걸 생성하지 않았는디.. 이렇게 치면 뭐가 나오네..?
Student.prototype  // 출력결과 >> {constructor: ƒ}

// 3. student의 prototype에 값을 줘볼까?
Student.prototype.gender = "남";

// 4. 학생1이라는 인스턴스 생성
var 학생1 = new Student("김태희", 15);

// 5. 학생1.genter를 지정하지 않았어도, prototype에 저장된 값이 노출된다.
학생1.gender;   // 출력결과 >> '남'

 

#1. prototype의 동작원리

1. 앞선 예제 에서 학생1.gender 이 어떻게 출력되는지 탐구해보자.

학생1.gender 호출시, 

1) 학생1이 직접 gender를 가지고 있는가?

-> 없음.

-> 부모유전자에서 gender 찾아보기. 이때 부모유전자는  Student.prototype이 된다.

 

2) 학생1의 부모 유전자(prototype)은 gender를 가지고 있는가?

-> 참이어서, gender 는 '남'이 출력된다.

 

 

2. 내장함수는 어떻게 돌아가는지?

1) array 

var arr = [1,2,3,4]; 

arr.toString(); // >> 출력결과 >> '1,2,3,4'
// arr에는 toString이라는 값이 없지만, 우리는 꺼내 사용할수있다. toString 을 찾아자.. 찾아.. 부모.. 부모.. 유전자까지 가기때문

- arr에 정의되지 않은 toString을 사용할 수 있는 이유는 var arr = [1,2,3,4] 는 모든 array는 new Array()라는 Array costructor를 통해 생성되기 때문이다.

var arr = new Array(1,2,3,4); // = var arr = [1,2,3,4];

Array.prototype // arr의 구조를 상속해주는 Array constructor는 prototype을 가지고있고..
// 그 prototype 안에 toString이 있다.

Array.prototype

 

 

2) object

- var obj = {name: '김윤아'} 이 함수는 var obj = new Object(); 로 Object가 만들어 진 후 할당되는 것이다. 

- 그래서 obj에는 toString이라는 함수가 정의되어있지 않더라도 Object.prototype에 있는 toString 을 불러와서 사용할 수 있다. 

var obj = {name: '김윤아'}
// == var obj = new Object();  // 모든 object자료형은 Object 부모를 이용해 이렇게 만들어짐.

obj.toString();  // 출력결과 >> '[object Object]'
Object.prototype  // 부모격인 Object.prototype이 toString을 가지고 있기 때문에 쓸수있음.

 

 

 

#prototype의 특징

- 그렇다고 prototype은 모두에게 있는건 아니다.

 

1. prototype은 constructor함수에만 몰래 생성된다.

- constructor가 아닌, 일반 object나 array .prototype 검색해봤자 안남옴.

var arr = [1,2,3,4];
arr.prototype;  // 출력결과 >> undefined

var obj = {name: '김사랑'};
obj.prototype; // 출력결과 >> undefined

 

2. 내 부모의 유전자(부모의 prototype)을 검사하고 싶으면 __proto__

- 앞에서 prototype을 찾지 못한 녀석들의 부모 유전자를 알고싶다면 .__proto__를 통해 찾을 수 있다.

var arr = [1,2,3,4];
arr.__proto__;  // 출력결과 >> 하단 이미지 참고

var obj = {name: '김사랑'};
obj.__proto__; // 출력결과 >> 하단 이미지 참고

- arr._proto__로 검색하면 아래 constructor에 Array가 있는걸 확인할 수 잇다.

arr.__proto__

- obj.__proto__도 마찬가지, constructor에 Object 가 담겨있는 것을 확인할 수 있다. 

obj.__proto__

3. __proto__ 이용하면 부모 강제 등록도 가능

- 자식.__proto__ = 부모; 이런식으로 대입해주면 부모를 강제로 등록도 가능하다. 그런데 자주 사용하진 않는다고함. 

var parent = {name: '김연아'};
var child = {};

child.__proto__ = parent;
console.log(child.name);  // 출력결과 >> 김연아

child.__proro__ 가 잘 등록되어있다.

4. 콘솔창에서 알려주는 prototype chain

- 하단 예제의 인스턴스(학생1)를 콘솔에 그대로 출력하면, prototype chain이 어떻게 생겼는지 확인 할 수 도 있다. 

// 1. Constructor 생성
function Student(name, age) {
    this.name = name; 
    this.age = age;
    this.sayHi = function(){
    	console.log(`안녕하세요 ${this.name} 입니다`); 
    }
}

// 2. 인스턴스 생성
var 학생1 = new Student("김태희", 15);

// 3. 학생1의 콘솔에는 뭐가 있을까?
학생1;  // 출력결과 >> 하단 이미지 참조

학생1의 prototype chain

- 학생1의 부모유전자는 Student,

- Student의 부모 유전자는 Object 임을 확인할 수 있다.