(본 포스팅은 개인 공부를 목적으로 작성된 포스팅으로 부족한 점이 있다면 댓글로 알려주시면 보완하겠습니다!)
<목차>
1. 프로토타입이란?
2. 생성자란?
3. 프로토타입 체인이란?
4. 프로토타입 사용시 주의사항
1. 프로토타입이란?
프로토타입이라는 것이 무엇일까?
프로토타입은 자바스트립트 안에 존재하는 거물급 개념중에 하나이고,
자바스크립트의 객체지향 언어를 지탱하고 있는 매우 핵심적인 개념 중에 하나이고,
자바스크립트를 일반적인 객체지향 언어와 구분하는 중요한 개념이다.
프로토타입은 '원형'이라는 의미로 말그대로 객체의 원형이라고 이해할 수 있다.
함수는 객체이다.
그러므로 생성자로 사용될 함수도 객체이다.
객체는 프로퍼티를 가질 수 있는데 prototype이라는 프로퍼티는 그 용도가 약속되어 있는 특수한 프로퍼티이다.
prototype에 저장된 속성들은 생성자를 통해서 객체가 만들어질 때 그 객체에 연결된다.
아래의 예를 보자.
function Large(){}
Large.prototype.largeProp = true;
function Medium(){}
Medium.prototype = new Large();
function Small(){}
Small.prototype = new Medium();
let i = new Small();
console.log(i.largeProp); //true
위의 예시를 보면 세개의 생성자(Large/ Medium/ Small)가 정의되어 있다.
그리고 맨 아래에서 Small의 객체(i)를 만들었을 때,
해당 객체 i의 largeProp에 접근했을 때, 결과값은 true가 나온다.
그런데 여기서 Small를 통해 만들어진 객체 i 자체는 largeProp이라는 값을 가지고 있지 않다.
그럼 어떻게 largeProp 이라는 값에 접근하여 사용이 가능한 것일까?
아래 그림으로 간단하게 정리해보았다.
위에서 말한 것들을 가능하게 하는 핵심적인 역할을 하는 프로토타입에 대해 알아보겠다.
2. 생성자란?
그전에 생성자라는 개념에 대해 알고 갈 필요가 있다.
생성자는 기본적으로 함수이다.
우리는 함수를 호출할때 new를 붙여주면, 해당 함수는 생성자가 된다.
그렇게 실행된 결과는 새로운 객체를 만들어서 리턴하기 때문에 i라는 변수 안에 생성자를 통해 만든 객체가 들어있다.
이것이 생성자의 역할이다.
하지만 단순히 빈객체를 만들어내는 것이 생성자의 역할이라면 큰 의미는 없을 것이다.
//아래처럼 작성해도 빈 객체를 만들어 낼 수 있기 때문이다.
let i = {};
그런데 굳이 생성자를 통해 객체를 만드는 이유는 무엇일까?
우리가 어떤 객체를 만들때, 그 객체가 가지고 있어야하는 메서드,
또는 객체가 가지고 있어야할 데이터를 나타내는 프로퍼티 값을 기본적으로 가지고 생성되기를 원하기 때문이다.
우리가 얻고자 하는 객체(위에서 말한 필요한 메서드/프로퍼티 값을 가진 객체)의 원형이 저장되어 있는 곳이
바로 프로토타입이라고 하는 프로퍼티에 저장이 된다.
즉 Small이라고 하는 함수는 객체이기 때문에 프로퍼티를 가질 수 있다.
그 프로퍼티 중에서 '프로토타입'이라고하는 특수한 프로퍼티가 존재한다.
다시 말해서 '프로토타입'이라고 하는 프로퍼티 안에는 어떤 객체가 정의되어 있다.
그렇게 객체를 저장했다가, new 키워드를 통해서 생성자를 호출하면,
자바스크립트는 생성자 함수의 '프로토타입' 프로퍼티에 저장되어 있는 객체를 꺼내서 그것을 리턴한다.(생성하는 변수에 담긴다.)
3. 프로토타입 체인이란?
생성자 함수로 호출해서 만들어진 객체는 프로토타입이라는 객체가 리턴되는 것이다.
위의 그림으로 다시 이해해보면,
1. Small의 프로토타입에 할당되는 new Medium() 에는 Medium이라는 생성자가 만든 객체가 들어간다.
2. 이번에는 Medium의 프로토타입에 할당되는 new Large() 에는 Large라는 생성자가 만든 객체가 들어간다.
3. 그러면 Large의 프로토타입 값은 largeProp라는 값을 true로 가지고 있다.
4. 그래서 우리가 new Large() 로 객체를 생성하면 그렇게 생성된 객체 안에는
largeProp라고하는 프로퍼티 값이 true의 값으로 저장되어 있는 객체가 new Large()에 만들어지게 되는 것이다.
5. 바로 그것이 Medium의 프로토타입이 되는 것이다.
6. 다시 우리가 new Medium()으로 객체를 생성하면 Medium의 프로토타입에 저장되어 있는 객체가 new Medium()이 되는 것이다.
7. 그럼 마지막으로 new Medium()은 Small의 프로토타입으로 할당되는 것이다.
8. 그래서 결과적으로 우리가 new Small()을 하게되면 바로 Small이라고하는 생성자의 프로토타입 안에 있는
new Medium()이라는 객체가 new Small()로 들어와서 변수 i에 할당되고
9. i 에서 largeProp이라는 값에 접근할 수 있는 것이다.
=> 이런 개념을 [프로토타입 체인 (prototype chain)]이라고 한다.
그럼 위의 얘시를 조금 바꿔보겠다.
위의 코드를 실행해보면 1이라는 결과가 나온다.
자바스크립트에서 i.largeProp를 실행하게 되면 i라는 객체가 largeProp를 가지고 있는지 확인한다.
그런데 우리는 이미 i.largeProp에서 값을 지정했기 때문에 로그값이 1로 찍히는 것이다.
그럼 코드를 이렇게 바꿔보면, 결과값은 2가 나온다.
위에서 말한 것처럼, i.largeProp를 실행하면
1. i가 largeProp를 가지고 있는지 확인한다.
2. 가지고 있지 않다.
3. i 객체에 직접적으로 largeProp라는 값은 없다라는 것을 자바스크립트가 인지함.
4. i 객체의 생성자를 알아낸다.
5. i 객체가 Small()이라는 것을 알고, 그 안을 확인해서 그 객체의 프로퍼티 중에서 largeProp라는 값이 있는지 확인한다.
6. largeProp 라는 값이 있다면 콘솔 로그에 돌려준다.
이와 같은 논리로 생각해보면 아래의 사진도 쉽게 이해가 될 것이다.
4. 프로토타입 사용시 주의사항
여기서 주희할 점은 Small.prototype에 할당된 객체는 상속받고자 하는 객체 자체(new Medium())를 넣어줘야 한다는 것이다.
만약 이렇게 작성하지 않고, Medium.prototype 과 같이 작성하게 되면,
자식에게 일어나는 일이 부모에게도 반영되기 때문에 이렇게 작성하면 여러 문제를 발생할 수 있다.
그래서 어떠한 객체를 상속받을 때에는 상속받고자 하는 객체의 프로토타입을 사용하는 것이 아니라
그 프로토타입을 통해 만들어진 생성자를 사용해야 한다.
이렇게 간단하게 프로토타입의 메커니즘에 대해 알아봤습니다.
질문과 지적은 댓글로 환영합니다!
긴글 읽어주셔서 감사하고 오늘도 즐코하세요!! :)
참고자료
https://poiemaweb.com/js-prototype
https://www.nextree.co.kr/p7323/
https://www.youtube.com/watch?v=673mZ8rE9UY
'Web' 카테고리의 다른 글
[Library] Helmet - header에 사용함으로써 express 보안 강화 (2) | 2022.05.04 |
---|---|
객체지향 프로그래밍이란? OOP (Object Oriented Programming) 정리 (0) | 2022.05.03 |
[ MySQL ] primary key / unique key 비교 (0) | 2022.04.29 |
VSCode 주석 색깔 변경하기 (0) | 2022.04.27 |
[ MySQL ] mysql 사용법 총정리 기본 명령어 ( cheat sheet ) (0) | 2022.04.25 |