ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JavaScript 프로토타입
    프로그래밍 언어/JavaScript 2022. 1. 13. 21:21

    클래스 기반의 객체지향 언어 VS 프로토타입 기반의 객체지향 언어

    객체(Object)를 중심으로 서로 상호작용하며 작동하는 프로그래밍 기법을 객체 지향 프로그래밍이라 한다. 그리고 JavaScript 역시 이러한 객체 지향 프로그래밍을 지원하는 언어이다.

     

    하지만 일반적인 객체 지향 언어와 JavaScript는 서로 다른 점이 있다.

     

    Java, Python, C#과 같은 클래스 기반의 객체 지향 언어의 경우, 클래스를 이용해 데이터와 메서드를 적절히 구성하고, 이를 활용하여 새로운 객체(인스턴스)들을 생성하고 사용한다.

     

    반면 JavaScript에는 클래스라는 개념이 없다. 따라서 클래스를 이용해 객체를 생성하고, 클래스끼리 데이터를 상속받는 등의 클래스 기반의 객체 지향 언어의 방식은 사용할 수 없다.

    대신 JavaScript는 프로토타입을 기반으로 하는 객체 지향 언어이기 때문에, 이 프로토타입(Prototype)이라는 개념을 이용하여 객체를 생성하고, 데이터도 연결하는 방식을 사용할 수 있다.

     

    참고로 ES6 이후에는 JavaScript에 Class 문법이 정식으로 추가되었다. 다만 이는 Class라는 키워드가 추가되다는 것일 뿐, JavaScript가 클래스 기반의 언어로 변했다는 것이 아니다.


    프로토타입이란?

    JavaScript에서 어떠한 객체(Object)를 생성하기 위해서는 new라는 키워드와 생성자 함수를 사용한다.

    생성자 함수란 객체를 생성하는 함수이며, 이는 생성자 함수라는 이름에 걸맞게 함수의 형태를 가진다.

    생성자 함수 (Constructor Function)

    객체를 생성하는 데에 사용되는 생성자 함수는 JavaScript에 기본적으로 내장된 것도 있고, 직접 정의하여 사용할 수도 있다.

     

    JavaScript에 기본적으로 내장된 생성자 함수로는 기본적으로 Object, Array, Function, Date 등이 있으며, 이들을 이용해 아래의 코드와 같이 객체들을 만들 수 있다.

    const obj = new Object();
    const arr = new Array();
    const func = new Function();

    물론 이러한 생성자 함수를 사용하지 않더라도, 흔히 사용하듯이 아래와 같은 리터럴 방식으로 객체를 생성할 수 있다. 해당 방법이 훨씬 간단하면서도 안정적이고, 빠르기에 특별한 경우를 제외하고는 굳이 위의 방법을 택할 이유는 없다.

    (리터럴 방식을 사용해도 내부적으로는 해당되는 생성자 함수를 이용해 생성하는 방식과 동일하게 작동한다.)

    const obj = {};
    const arr = [];
    function func() {}

    참고로 생성자 함수로 생성하는 것들은 모두 객체이고, 이는 배열이나 함수 역시 객체에 해당된다는 것을 의미한다. 이에 대한 자세한 내용은 후에 따로 글을 쓰도록 하겠다.

     

    이렇게 위와 같은 내장 생성자 함수를 이용하여 특수한 목적을 가지는 객체를 생성하듯이, 프로그램 제작 중 필요한 특정 객체를 생성하기 위한 생성자 함수를 직접 만들어 사용할 수도 있다.

     

    생성자 함수를 만들기 위한 방법은 아래와 같다.

    function MyFunction(nickname) {
      this.nickname = nickname;
    }
    
    const myObject = new MyFunction("Cookie");

    뭔가 특별한 방법이 있을 것 같지만, 사실은 전혀 특별할 것이 없는 전형적인 함수 생성 방식이다.

    즉, 모든 함수를 생성자 함수로 사용할 수 있다. 어떤 함수라도 new 키워드와 함께 사용한다면, 일반적인 함수 호출 작업에 객체 생성이라는 추가 작업을 수행할 뿐이다.

     

    이렇게 new 키워드와 함께 함수를 호출하게 되면, 해당 함수 내에 return문이 없어도 새로운 객체를 반환시킨다.

    그리고 이때 생성되는 객체의 초기 데이터를 생성자 함수 내에서 this를 이용해 정의할 수 있다.

    (위의 코드에서 생성자 함수 내의 this는 new MyFuction()으로 생성되는 개별 객체를 의미한다.)

     

    그렇다면 이러한 생성자 함수의 존재 이유는 무엇일까?

    바로 생성자 함수, 즉 모든 함수는 프로토타입(prototype)이라는 property를 가질 수 있기 때문이다.

    이러한 프로토타입이 무엇이고, 어떠한 역할을 하는지는 아래에서 설명한다.

    프로토타입 프로퍼티 (prototype property)

    우선 prototype이라는 property가 어떻게 생겼는지를 직접 살펴보자.

    생성자 함수 객체의 property를 확인하기 위해 console.dir 메서드를 아래와 같이 사용하였다.

    function MyFunction(nickname) {
      this.nickname = nickname;
    }
    
    const myObject = new MyFunction("Cookie");
    
    console.dir(MyFunction);
    console.dir(myObject);

    해당 js파일을 빈 html 파일에 연결하여 브라우저에 띄운 후, 크롬 브라우저의 개발자 모드(F12)로 확인해보면 아래 사진과 같은 데이터를 얻을 수 있다.

    console.dir 메서드를 이용해 각 객체의 property를 확인

    가장 처음의 log는 생성자 함수이고, 그다음 log는 해당 생성자 함수와 new 키워드로 생성한 myObject라는 객체이다.

    해당 log들을 펼쳐보면 각 객체가 가지고 있는 property들을 확인할 수 있다.

     

    myObject

    우선 두 번째 log인 myObject 객체에 대해 먼저 알아보자.

    당장 확인할 수 있는 property는 nickname과 [[Prototype]] 2가지가 있다.

     

    nickname이라는 property는 해당 myObject객체를 생성하기 위해 사용한 생성자 함수인 MyFunction에서 this를 이용해 미리 지정한 property이다. 따라서 위의 코드를 살펴보면, MyFunction 함수를 new 키워드와 함께 사용하면서 넘긴 인수인 "Cookie"가 그대로 nickname이라는 property로 저장된 것을 확인할 수 있다.

     

    [[Prototype]]에 대해서는 아래에서 다시 제대로 다루겠다. 지금은 이것이 우리가 찾으려는 prototype property가 아니라는 것만 확실히 알아두면 된다.

     

    MyFunction

    다음으로는 첫 번째 log인 MyFunction 객체에 대해 알아보자.

    MyFunction은 함수 객체이기에 함수가 가지고 있는 기본 property인 arguments, caller, length, name 등을 가지고 있다.

     

    그리고 다음으로 가장 눈에 띄는 것이 prototype이라는 이름의 property이다. 바로 이 property가 우리가 직접 확인하려는 바로 그 property이다.

    이는 위에서 살펴본 myObject 객체의 log에서는 발견할 수 없었던 property로 오직 함수 객체에서만 발견할 수 있다.

     

    이 prototype이라는 property를 확장하여 자세히 살펴보면 아래와 같다.

    prototype property를 확장하여 데이터 확인

    prototype안에는 consturctor와 [[Prototype]]이 보인다. [[Prototype]]은 아까 전의 myObject에도 있었고, MyFunction에도 있고, 심지어 MyFunction의 prototype property 안에도 있다.

    이놈이 대체 뭐하는 놈인지는 궁금하겠지만, 아직은 모든 객체에 존재하는 일종의 Link라고만 알아두고 넘어가자.

     

    다시 돌아와서 이 prototype property가 대체 무엇을 나타내는 것인지 이제는 제대로 알아보자.

    prototype property
    함수 객체만이 가질 수 있는 property로, 해당 함수를 이용해 생성된 객체들이 원형으로 사용할 객체를 의미한다.

    JavaScript의 모든 객체는 자신을 생성한 객체 원형에 대한 숨겨진 연결을 갖는다. 그리고 자기 자신을 생성할 때 사용한 그 객체 원형을 프로토타입(Prototype Object)이라고 한다.

     

    이때 모든 객체는 생성자 함수에 의해 생성되므로, 자기 자신을 생성할 때 사용한 객체 원형(Prototype Object)이라는 것은 생성자 함수 객체 자체를 의미하는 게 아닐까?

    반은 맞지만 반은 틀렸다. 정확히는 해당 생성자 함수의 prototype property를 의미한다.

     

    어떠한 함수든 정의가 된 순간, 객체를 생성하기 위해 사용될 가능성이 있다. 그리고 실제로 그 함수와 new 키워드를 이용해 객체를 만들게 된다면, 그 객체는 자신을 만든 객체 원형(Prototype Object)과 연결을 가져야 할 것이다.

     

    따라서 함수는 자신이 생성한 객체에게 제공할 객체 원형(Prototype Object)를 가지고 있어야 하고, 이것이 바로 함수 객체의 prototype property이다. 즉, 함수 객체의 prototype property가 해당 함수로 생성된 객체의 원형인 Prototype Object가 되는 셈이다.

     

    이때 함수 객체의 prototype property는 해당 함수 객체의 여러 정보를 가지고 있다.

     

    위의 사진에서 함수 객체의 prototype property에 있는 여러 정보 중, constructor라는 것이 있다.

    이는 해당 Prototype Object를 객체 원형으로 삼는 객체를 생성하기 위한 생성자 함수를 의미한다.

    쉽게 말해서 MyFunction에 있는 prototype property의 constructor는 MyFunction을 가리킨다.

     

    이는 아래와 같이 console창에 직접 적어서 확인해 볼 수도 있다.

    이러한 이유로 MyFunction에 있는 prototype property에서 consturctor부분을 다시 펼친다면, 처음의 MyFunction과 동일한 property들을 확인할 수 있을 것이고, 이를 무한히 반복하는 것도 가능하다.

    함수 객체의 prototype property의 constructor는 그 함수 객체 자신을 의미한다. 따라서 console창에서 무한히 반복할 수 있다.

    위와 같은 행동은 아무런 의미가 없는 행동이다. 다만 장난 삼아 계속 열어본다면, 해당 constructor가 함수 객체 자체를 뜻한다는 것을 확실이 몸소 느낄 수 있을 것이다.

    프로토타입 링크 (Prototype Link)

    이번에는 지금까지 모든 객체에서 계속해서 발견되던 의문의 [[Prototype]]이라는 property에 대해 알아본다.

     

    위에서 prototype property를 설명하면서, JavaScript의 모든 객체는 자신을 생성한 객체 원형에 대한 숨겨진 연결을 갖는다고 했었다. 이때 이 숨겨진 연결이 바로 [[Prototype]]이며, 이를 프로토타입 링크라고 부른다.

     

    모든 객체는 생성자 함수에 의해 생성되고, 해당 생성자 함수가 가진 property인 prototype을 객체 원형으로 하는 연결을 가지게 된다. 그리고 이 연결이 바로 [[Prototype]]인 것이다.

     

    이를 위에서도 사용했던 아래의 코드를 이용해 간단하게 설명하면 다음과 같다.

    function MyFunction(nickname) {
      this.nickname = nickname;
    }
    
    const myObject = new MyFunction("Cookie");
    
    console.dir(MyFunction);
    console.dir(myObject);

    위의 코드에서는 MyFunction이라는 생성자 함수와 new 키워드를 이용해 myObject라는 새로운 객체를 생성하였다. 이때 MyFunction 함수에는 prototype이라는 property가 있을 것이고, myObject 객체는 [[Prototype]]이라는 프로토타입 링크를 통해 MyFunction의 prototype property와 연결을 가질 수 있다.

     

    따라서 사실상 생성자 함수의 prototype property와 그 생성자 함수로 생성한 객체의 [[Prototype]]은 아래의 사진에서 보이듯 서로 같다.

    생성자 함수 MyFunction의 prototype 프로퍼티와 생성된 객체 myObject의 [[Prototype]]이 서로 같다.

    객체가 이러한 프로토타입 링크를 이용하여, 실제 자신의 원형이 되는 Prototype Object에 접근하기 위해서는 Object.getPrototypeOf() 라는 메서드를 사용하면 된다. 또는 ES6 기준으로 __proto__라는 방식을 사용할 수도 있다.

     

    이러한 방식을 사용하여 실제로 생성자 함수의 prototype property와 그 생성자 함수로 생성한 객체의 [[Prototype]]이 같은지를 비교해보면 아래와 같은 결과를 얻을 수 있다.

    생성자 함수의 prototype 프로퍼티와 생성된 객체의 [[Prototype]]은 서로 같은것을 가리킨다.

    프로토타입 오브젝트, 프로토타입 프로퍼티, 프로토타입 링크 정리

    지금까지 JavaScript의 프로토타입이라는 개념을 간단히 살펴보았다.

    하지만 프로토타입 오브젝트, 프로토타입 프로퍼티, 프로토타입 링크 등 단어가 서로 너무 비슷하기에 처음 접한 사람의 입장에서는 너무나도 헷갈린다.

     

    따라서 이를 도식화하여 간단하게 표현하자면 다음과 같다.

    MyFunction 생성자 함수와 이를 이용해 만든 객체인 myObject1, myObject2, myObject3

    위의 그림은 MyFunction 생성자 함수와 이를 이용해 만든 객체인 myObject1, myObject2, myObject3의 관계를 보기 좋게 도식화한 것이다.

     

    1. 생성자 함수와 프로토타입 오브젝트

    생성자 함수를 생성하면, 자동으로 해당 생성자 함수에 대한 프로토타입 오브젝트가 생성된다. 그리고 생성자 함수에서는 prototype이라는 프로퍼티를 이용해 MyFunction.prototype과 같은 방식으로 자신과 동시에 생성된 프로토타입 객체에 접근할 수 있다.

     

    즉, 생성자 함수의 프로토타입 프로퍼티는 그 생성자 함수가 정의됨과 동시에 같이 생성된 프로토타입 오브젝트를 의미한다.

    또한 해당 프로토타입 오브젝트에 있는 constructor는 반대로 자신이 생성될 때 같이 선언된 바로 그 생성자 함수를 가리킨다. 따라서 아래와 같은 식이 성립할 수 있다.

     

    2. 프로토타입 오브젝트와 프로토타입 링크

    이번에는 MyFunction이라는 생성자 함수로 생성한 객체인 myObject1, myObject2, myObject3를 살펴보겠다.

    각 객체는 모두 [[Prototype]]이라는 프로토타입 링크를 가지고 있다. 이는 위에서 설명했듯이 자신을 생성한 객체 원형에 대한 숨겨진 연결을 의미하고, 이는 다시 말해 자신을 생성한 객체인 MyFunction의 프로토타입 오브젝트를 의미한다.

     

    따라서 MyFunction 함수로 생성한 객체 3개는 모두 MyFunction.prototype과 연결되어 있고, 이는 Object.getPrototypeOf() 메서드를 이용하거나 __proto__라는 프로퍼티를 이용하여 확인할 수 있다.

    생성자 함수와 함께 생성된 프로토타입 오브젝트를 객체 원형으로 하는 객체는 프로토타입 링크로 해당 객체에 접근할 수 있다.

    쉽게 말해 모든 객체에 존재하는 [[Prototype]]은 어찌 보면 자신의 부모와도 같은 것이다.

    모든 객체는 함수로 생성되고, 모든 함수는 생성과 동시에 프로토타입 오브젝트를 가지므로, 객체는 자신을 생성한 함수의 프로토타입 오브젝트와 부모와 자식의 관계를 가지는 셈이다.


    프로토타입 체인 (Prototype Chain)

    지금까지 JavaScript에서 프로토타입이라는 개념이 어떤 것인지를 살펴보았다.

    그렇다면 이러한 프로토타입이라는 개념이 존재하는 이유가 무엇일까?

     

    이를 위해 먼저 프로토타입 체인이라는 개념에 대해 알 필요가 있다.

    프로토타입 체인 (Prototype Chain)
    객체의 생성에서 원형 객체로 사용되는 프로토타입 오브젝트와의 연결고리를 의미하며, JavaScript에서는 이러한 연결이 계속해서 상위 프로토타입 오브젝트로 연속해서 이어지는 형태를 가진다. 이러한 연결 관계 자체를 프로토타입 체인이라고 한다.

    위에서 프로토타입 개념 설명을 위해 사용한 도식표를 다시 가져와서 보면, myObject1, myObject2, myObject3가 프로토타입 링크로 MyFunction.prototype이라는 프로토타입 오브젝트에 연결된 것을 볼 수 있다. 이러한 연결 자체를 프로토타입 체인이라고 한다.

    그렇다면 이렇게 프로토타입 체인을 통해 상위 프로토타입 오브젝트에 연결됨으로써 객체가 가지는 이득은 대체 뭘까? 바로 하위의 객체가 상위의 프로토타입 객체의 프로퍼티나 메서드를 공유받을 수 있다.

     

    이를 아래의 코드를 통해 알아보면 다음과 같다.

    function MyFunction(nickname) {
      this.nickname = nickname;
    }
    
    MyFunction.type = "func";
    MyFunction.prototype.color = "violet";
    
    const myObject = new MyFunction("Cookie");

    이전의 코드와 비슷하지만, 생성자 함수 객체에 새로운 프로퍼티를 추가하였다.

    type이라는 프로퍼티는 MyFunction에 직접적으로 부여하였고, color의 경우 MyFunction의 프로토타입 오브젝트에 부여한 것이다.

     

    이게 어떤 식으로 작동하는지, 서로 어떻게 다른지는 아래와 같이 console창에서 직접 확인할 수 있다.

    MyFunction의 프로퍼티 확인

    type의 경우 MyFunction에 직접적으로 부여한 프로퍼티이기 때문에 MyFunction에서 바로 접근이 가능하다.

    하지만 이는 MyFunction에 부여된 프로퍼티일 뿐이기 때문에, MyFunction의 프로토타입 오브젝트에는 전혀 영향을 미치지 않는다.

     

    color의 경우 MyFunction이 아닌 MyFunction의 프로토타입 오브젝트에 부여된 프로퍼티이기에 MyFunction에서 바로 접근이 불가능하다. 따라서 MyFunction.prototype.type과 같은 방식으로 프로토타입 오브젝트에 접근하여 color 프로퍼티에 접근해야 한다.

     

    이번에는 MyFunction 함수로 생성한 객체인 myObject의 작동에 대해서 알아보겠다.

    myObject의 프로퍼티 확인

    위의 코드에서는 MyFunction의 프로퍼티를 변경했을 뿐이지, myObject에는 어떠한 변화도 주지 않았다.

    하지만 2번째 log인 myObject.color를 보면 "violet"이라는 값에 접근할 수 있음을 확인할 수 있다.

    3번째 log에서 myObject의 프로퍼티를 확인해보면 nickname 밖에 없는데 대체 어디서 color라는 프로퍼티를 가져올 수 있었을까?

     

    이는 바로 모든 객체에 있는 프로토타입 링크인 [[Prototype]]을 통해서 가능한 일이다. 모든 객체는 자신이 가지고 있지 않은 프로퍼티에 접근하는 경우, 해당되는 프로퍼티를 찾을 때까지 프로토타입 링크를 이용해 상위의 프로토타입 오브젝트의 프로퍼티들을 탐색한다. 최상위 프로토타입 오브젝트까지 도달해서도 해당되는 프로퍼티를 찾지 못하는 경우에만 undefined를 리턴한다.

     

    따라서 myObject.color를 이용해 color 프로퍼티에 접근하려 한 순간 다음과 같은 순서로 값에 접근한 것이다.

    1. myObject객체에 color라는 프로퍼티가 있는지 확인한다. → 없음
    2. 프로토타입 링크를 이용해 myObject객체의 프로토타입 객체(MyFunction.prototype)를 찾는다.
    3. 해당 프로토타입 객체(MyFunction.prototype)에 color라는 프로퍼티가 있는지 확인한다. → 있음
    4. 해당 프로퍼티에 접근하여 값을 가져온다.

    이러한 경로로 myObject 객체는 color라는 프로퍼티를 가지고 있지 않지만, 해당 접근에 대한 값을 자신의 프로토타입 객체에서 찾아 반환할 수 있었다.

     

    반면 type이라는 프로퍼티는 undefined의 결과를 나타냈다. type의 경우 MyFunction이라는 함수 객체에 부여한 프로퍼티일 뿐이라, MyFunction.prototype에는 영향을 주지 않는다.

    즉, MyFunction 함수로 생성한 객체들과 연결된 프로토타입 오브젝트에는 type이라는 프로퍼티가 존재하지 않는다.

     

    따라서 JavaScript의 모든 객체는 자신에게 없는 프로퍼티라도 자신의 부모가 되는 프로토타입 오브젝트를 이용해 해당 프로퍼티를 찾아서 반환할 수 있다. 그리고 이러한 개념은 프로토타입 오브젝트를 공유하는 개념이기에, 같은 프로토타입 오브젝트를 부모로 하는 객체들은 모두 같은 프로퍼티를 공유하는 셈이 된다.

     

    이는 클래스의 상속의 개념과는 비슷하지만 약간 다른 공유의 개념이지만, 클래스의 사용법과 비슷하게 사용할 수 있으며, 이를 제대로만 알고 사용한다면 훨씬 더 효율적으로 객체들을 관리하는 것이 가능하다.

    생성자 함수의 프로토타입 체인 확인

    위의 프로토타입 체인 도식화를 더 자세히 보면 MyFunction과 MyFunction.prototype에도 [[Prototype]]이라는 상위 프로토타입 오브젝트와 연결할 수 있는 프로토타입 링크가 보인다. 이 링크는 그럼 어디로 이어지는 걸까? 그리고 올라가고 올라가다 보면 결국 어디에 도달하게 되는 걸까?

     

    아래는 JavaScript에서 생성자 함수를 이용해 객체를 생성했을 때의 전체 구성을 나타낸 것이다.

    위의 사진은 굉장히 복잡해 보이지만, 지금까지 공부한 내용을 바탕으로 하나하나 설명해서 풀이하면 생각보다 쉽게 이해를 할 수 있을 것이다.

     

    myObject1

    myObject1이라는 객체는 new Object() 코드를 통해 생성되었다. 즉, Object라는 내장 생성자 함수를 통해 생성되었고, 따라서 Object.prototype을 프로토타입 오브젝트로 둔다.

    그래서 myObject1의 프로토타입 링크([[Prototype]])를 보면, Object.prototype과 연결되어 있다.

     

    myObject2

    myObject2라는 객체는 new MyFuncction() 코드를 통해 생성되었다. 즉, MyFucntion이라는 생성자 함수를 통해 생성되었고, 따라서 MyFunction.prototype을 프로토타입 오브젝트로 둔다.

    그래서 myObject2의 프로토타입 링크를 보면, MyFunction.prototype과 연결되어 있다.

     

    MyFunction

    MyFunction이라는 함수 객체는 내부적으로 new Function() 코드를 통해 생성된다. JavaScript에서는 함수도 객체의 한 종류이므로 생성자 함수에 의해 생성되고, 이때 함수 객체를 생성하는 생성자 함수가 바로 Function인 것이다. 따라서 MyFunction 함수 객체는 Function의 프로토타입 프로퍼티인 Function.prototype을 프로토타입 오브젝트로 두게 된다.

    이러한 이유로 MyFunction함수의 프로토타입 링크는 Function.prototype과 연결되어 있다.

    또한 MyFunction 자체도 생성자 함수이므로, 자신을 통해 생성된 객체들이 부모로 삼을 프로토타입 오브젝트를 제공해야 한다. 따라서 MyFunction.prototype이라는 프로토타입 오브젝트가 자동으로 생성되며, 이는 MyFunction의 prototype이라는 프로퍼티를 통해 접근할 수 있다.

     

    MyFunction.prototype

    MyFunction.prototype은 MyFunction이라는 생성자 함수가 생성됨과 동시에 자동으로 생성되는 프로토타입 오브젝트이다. MyFunction 생성자 함수에는 Consturctor 프로퍼티를 이용해 접근할 수 있다.

    이때 프로토타입 오브젝트(객체) 역시 객체라고 할 수 있으므로, MyFunction.prototype도 [[Prototype]]이라는 프로토타입 링크를 가진다. 그리고 해당 링크는 Object.prototype과 연결되어 있다.

    이는 생성자 함수와 함께 생성되는 프로토타입 오브젝트가 내부적으로는 Object 생성자 함수로 생성된다는 것을 의미한다.

     

    Function

    Function은 함수 객체를 생성할 때 사용하는 내장 생성자 함수이다. Function 역시 함수이자 객체이므로 prototype 프로퍼티와 프로토타입 링크를 가지고 있는데, 이때 이 둘 모두 Function.prototype에 연결되어 있는 것을 확인할 수 있다.

     

    먼저 Function의 prototype 프로퍼티의 경우, 해당 Function이 생성될 때 동시에 생성된 프로토타입 오브젝트인 Function.prototype을 가리키는 것이 당연하다.

     

    근데 Function의 프로토타입 링크도 똑같이 Function.prototype을 가리킨다. 프로토타입 링크는 자신의 부모 격이 되는 프로토타입 오브젝트를 가리키는데, 자신과 같이 생성된 프로토타입 오브젝트가 자신의 부모가 된다는 건 이해하기 힘든 일이다.

    하지만 Function 역시 일단은 함수이고, 모든 함수의 부모 객체는 Function.prototype이니 이는 어쩔 수 없는 일이다.

     

    Function.prototype

    Function.prototype은 Function 생성자 함수의 prototype 프로퍼티로, Function 생성자 함수로 생성되는 모든 함수 객체들의 부모가 되는 프로토타입 오브젝트이다.

     

    constructor로는 모든 함수를 생성하는 생성자 함수인 Function을 가리키고 있다.

    또한 해당 프로토타입 오브젝트 역시 객체이기 때문에 프로토타입 링크를 가지고 있는데, 해당 링크는 모든 객체들의 부모인 Object.prototype을 향하고 있다.

     

    Object

    Object는 객체를 생성할 때 사용하는 내장 생성자 함수이다. Object 역시 생성자 함수이므로 prototype이라는 프로퍼티를 가지고, 이는 Object 함수와 함께 생성된 프로토타입 오브젝트인 Object.prototype에 연결되어있다.

     

    그리고 프로토타입 링크는 Function.prototype에 연결되어 있다. 모든 함수의 부모는 Function.prototype이고, Object도 함수이기 때문에 이는 당연하다.

     

    Object.prototype

    Object.prototype은 Object 생성자 함수의 prototype 프로퍼티로, Object 생성자 함수로 생성되는 모든 객체들의 부모가 되는 프로토타입 오브젝트이다.

     

    constructor로는 모든 객체를 생성하는 함수인 Object를 가리키고 있다.

    그리고 프로토타입 링크는 null을 반환한다. 즉, 더 이상 부모에 해당하는 프로토타입 오브젝트가 없다.

    따라서 Object.prototype이 가장 최상위의 프로토타입 오브젝트라고 생각할 수 있다.

    정리

    위에서 배운 내용을 바탕으로, 이번에는 MyFunction이라는 생성자 함수로 생성한 객체인 myObject에 대한 내용을 도식화한 것이다.

    아래의 내용에 대해 완벽하게 이해가 가능하다면, 해당 포스트에 대한 모든 내용을 제대로 이해한 것이다.


    마무리

    이번 포스트에서는 JavaScript의 프로토타입 시스템에 대해 알아보았다.

    서로 이름도 비슷하고, 서로가 서로를 가리키는 상황이 굉장히 헷갈리기 때문에, 같은 내용을 계속 반복해서 설명하는 방식으로 글을 적었다.

     

    이번 글을 통해 JavaScript의 프로토타입 시스템에 대해 이해했다면, 이를 활용하는 방식 또한 함께 공부하는 것을 추천한다. 기회가 된다면 이에 대한 포스팅도 함께 올리고 아래에 링크를 추가하도록 하겠다.

    댓글