프로토타입(Prototype)

박제구·2021년 8월 31일
0

JavaScript

목록 보기
6/6
post-thumbnail

🧩 프로토타입(Prototype) 이란?

자바스크립트는 프로토타입 기반의 언어이다.

그렇다면 프로토타입은 무엇일까?

프로토타입은 자바스크립트에서 자신을 생성한 객체의 원형을 의미한다.

모든 객체는 자신의 부모 객체와 연결되어 있고, 이 프로토타입을 이용하면 객체지향의 상속처럼 속성을 사용할 수 있게 해준다.

프로토타입은 추상적인 용어로 헷갈리는 부분이 많기 때문에 아래부터는 예시와 함께 이해하도록 한다.

🧩 프로토타입 객체 [[prototype]] & prototype property

function Student(name, age){
    this.name = name
    this.age = age
}

const A = new Student('Park', 20)

생성자 함수를 통해 A라는 객체를 생성했다.


A객체와 Student함수객체를 확인해보면, 두 객체는 [[prototype]] 을 갖고 있다.
하지만 prototype 이라는 프로퍼티는 함수객체인 Student만 갖고 있는 것을 알 수 있다.

  • [[prototype]]
    1. 자바스크립트의 모든 객체가 갖고 있다.
    2. 프로토타입 link라고 표현하기도 하는데, __proto__ 로 접근할 수 있다.
    3. 조상 객체의 프로토타입 정보를 갖고 있다, 즉 자신을 만들어낸 객체의 원형을 가리킨다.
  • prototype property
    1. 자바스크립트의 함수 객체만 갖고 있다.
    2. 프로토타입 Object라고 표현하고, constructor를 갖고 있다.
    3. 자신을 원형으로 만들어질 새로운 객체

위의 예시를 살펴보면,

  1. Student 함수 객체의 프로토타입 프로퍼티는 constructor를 갖고 있고 constructor는 원형 객체인 Student 를 가리킨다. (상호참조)
  2. Student 생성자 함수로 만들어진 A는 [[prototype]]을 갖고 있고, 자신을 생성한 Student객체의 프로토타입을 가리킨다.
Student.prototype.constructor === Student
// true
A.__proto__ === Student.prototype
// true

Student 라는 함수 객체도 [[prototype]] 이 있고, 이를 통해 상위 객체의 프로토타입을 참조하고 있는 것을 알 수 있는데, 과연 이 prototype의 끝은 어디 일까?

자바스크립트에서는 함수도 객체이다.
Function 이라는 키워드는 함수이자 객체라고 할 수 있고, 이 또한 prototype을 갖는다.

결국 Student 객체의 [[prototype]]은 Function의 prototype property를 의미한다.

Student.__proto__ === Function.prototype
// true

프로토타입 property의 루트는 Object prototype이다.
-> 자바스크립트의 모든 객체는 Object 에서 파생되고, 함수 또한 마찬가지이다.

따라서 아래와 같은 결과를 확인 할 수 있다.

/* 1 */
Student.__proto__ === Function.prototype // true

/* 2 */
Function.prototype.__proto__ === Object.prototype // true

/* 3 */
Student.prototype.__proto__ === Object.prototype // true

/* 4 */
Object.prototype.__proto__ // null

🧩 프로토타입 체인

프로토타입을 통해 상위 객체의 속성과 메소드를 연결하는 것

위 개념에서 본 [[prototype]] 즉, _ _proto_ _를 통해 최상위 Object prototype까지 접근 할 수 있다는 것을 알았고, 연결하면서 공유된 모든 속성과 메소드를 사용할 수 있는 것이 프로토타입 체인이라고 할 수 있다.

지금 까지 프로토타입이 무엇인지 몰랐어도, 사실은 자바스크립트를 사용하면서 자연스럽게 프로토타입 체인을 사용하고 있었다.

const myStr = "abc"

console.log(myStr.toUpperCase())
// "ABC"

myStr 어디를 찾아보아도 메소드를 정의하지 않았다.
myStr 이라는 스트링을 선언했을 뿐인데 만들어 놓지도 않은 toUpperCase라는 함수를 사용할 수 있다.
당연하듯 사용해 왔지만, 사실 프로토타입 체인 을 통해 가능한 일이다.

myStr.__proto__ === String.prototype
// true

String 이라는 키워드는 함수이고 const myStr = "abc" 를 했을 때 String prototype을 연결하여 myStr 객체를 생성한다.

즉, String 은 prototype 프로퍼티 를 갖고 있고, myStr 의 [[prototype]]이 연결하고 있다.

String 안에 prototype 프로퍼티가 있고, 그곳에 여러 스트링에 사용될 메소드들이 정의되어 있다.(toUpperCase도 여기에!)

만약 현재 객체에 없는 속성을 호출하면, 프로토타입 체인을 통해 상위 객체의 프로토타입 프로퍼티를 확인하고 없으면 최상위 Object prototype의 property까지 확인한다.

Object.prototype.size = function(){
    console.log(`size -> ${this.length}`)
}

length라는 속성으로 string 객체의 크기를 알 수 있지만, size라는 함수로 접근하기 위해
최상위 Object의 프로토타입 속성에 size함수를 정의하였다.

myStr.size()
// "size -> 3"

myStr 에 없음 -> String prototype에 없음 -> Object prototype

이렇게 _ _proto_ _값을 연결하여 프로토타입 체인으로 연결된 속성들을 사용할 수 있다.

최상위 Object에도 없으면? -> 에러발생

🧩 프로토타입 사용해보기

const fruit = ["apple", "banana", "peach"]

배열에서 마지막 값을 리턴해주도록 만들고 싶다.

물론, 함수로 만들어 사용하거나 배열의 크기를 가지고 매번 값을 얻을 수 있다.
하지만 프로토타입을 이용하면 가독성 있고, 재사용성 높은 코드작성이 가능하다.

모든 Array에 적용하고 싶기 때문에

Array.prototype.getLastValue = function(){
    return this[this.length-1]
}

이렇게 작성해준다.

const lastFruit = fruit.getLastValue()
console.log(lastFruit)
// "peach"

사실 지금까지 개발을 하면서 prototype을 건드려 본적은 없다..

하지만 큰 규모의 객체지향 프로그래밍에 적용한다면, 충분히 사용할 가치가 있는 개념인 것 같다.

References


poiemaweb

http://insanehong.kr/post/javascript-prototype/

https://mygumi.tistory.com/312

https://medium.com/@bluesh55/javascript-prototype-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-f8e67c286b67

profile
안녕하세요!

0개의 댓글