JavaScript 프로토타입, 클래스 개념 요약 정리

작성 : 2023-11-07수정 : 2023-11-07

목차 펼치기

프로토타입

JavaScript는 프로토타입 기반 언어다. 즉, 프로토타입은 JavaScript의 기반이 되는 개념이다. ‘클래스’라는 개념을 기반으로 ‘상속’을 구현하는 클래스 기반 언어와는 달리 한 객체를 원형으로 두고 이를 ‘복제’함으로써 유사한 효과를 얻는다.


용어 정리

  • 생성자 함수(Constructor)

    • 이름의 첫 시작은 항상 대문자여야 한다.

  • prototype
    • 생성자 함수에 존재하는 객체로 인스턴스에서 참조될 수 있다.

  • 스태틱 메서드(Static Method)

    • 생성자 함수 내에 정의된 함수

    • 인스턴스에서 직접 접근할 수 없다.

  • 프로토타입 메서드(Prototype Method)

    • 생성자 함수 내

      prototype

      내에 정의된 함수

    • 인스턴스에서 직접 접근할 수 있다.

  • 인스턴스(Instance)

    • 생성자 함수와

      new

      연산자를 통해 생성한 객체

  • __proto__

    • dunder proto(double underscore)라고 발음한다.

    • 인스턴스에 자동으로 부여되며 생성자 함수의

      prototype

      객체를 참조한다.

  • 메서드 오버라이딩

    • 상속 관계에서 부모 메서드를 재정의하는 기법

  • 메서드 오버로딩

    • 동일한 함수명으로 다른 매개변수를 가지는 여러 함수를 정의하는 기법

    • JavaScript는 동일한 함수명으로 덮어씌워지기 때문에 없는 개념이다.


__proto__

  • ES5.1 명세에서는

    [[prototype]]

    이라고 정의되어 있기도 하다.

  • ES6에서 브라우저의 레거시 호환을 위해 인정되기는 했으나, 직접 접근 하는 것은 권장되지 않는다.

  • Object.getPrototypeOf()

    또는

    Object.create()

    를 사용하는 것이 권장된다.

  • 태생부터 생략 가능한 프로퍼티다.

    • 즉, A 인스턴스를 사용할 때

      A.__proto__.getName()

      A.getName()

      은 동일하게 호출할 수 있다.

      하지만 메서드를 호출하는 객체가 다르기 때문에 두 방식의 this는 다르다.

특징

  • JavaScript는 함수에 자동으로

    prototype

    프로퍼티를 생성한다.

  • 함수를 생성자 함수로 사용할 경우, 즉

    new

    연산자와 사용할 경우 새로운 인스턴스를 생성한다.

  • 인스턴스에서는 숨겨진 프로퍼티인

    __proto__

    를 자동으로 생성하는데, 생성자 함수의

    prototype

    을 참조한다.

    • 즉, 인스턴스는 생성자 함수의

      prototype

      에 정의된 메서드와 프로퍼티에 언제든 접근할 수 있다.

    • 프로토타입 메서드는 인스턴스에서 메서드 오버라이딩을 통해 재정의 될 수 있다.

  • 생성자 함수의

    prototype

    내부에는 생성자 함수 자신을 참조하는

    constructor

    프로퍼티가 존재한다.

    • 이를 통해 인스턴스의 원형이 무엇인지를 알 수 있다.

    • number

      ,

      string

      ,

      boolean

      타입을 제외하고는 변경이 가능하나, 참조가 바뀔 뿐 타입이 변경되는 것은 아니다.


예시

json
1function Array() {
2	from(),
3	isArray(),
4	prototype: {
5		constructor: Array,
6		push(),
7		pop(),
8		...
9	}
10}
11
12const arr = [1];
13Array.isArray(arr); // true
14arr.push(2); // arr: [1, 2]
  • 생성자 함수 중 하나인

    Array

    from

    ,

    isArray

    등의 메서드는

    prototype

    내부에 선언되어 있지 않는 스태틱 메서드이기 때문에 생성자 함수를 통해서만 사용할 수 있다.

  • push

    ,

    pop

    등의 메서드는

    prototype

    내부에 선언되어 있는 프로토타입 메서드이기 때문에 인스턴스에서 접근이 가능하다.

  • consturctor

    프로퍼티를 통해 인스턴스의 원형을 알 수 있다.


프로토타입 체인

__proto__

는 객체이기 때문에, 기본적으로

모든 객체

__proto__

Object.prototype

과 연결된다. 이처럼

__proto__

프로퍼티가 연쇄적으로 이어진 것을 ‘프로토타입 체인’이라고 하며, 이 체인을 따라가며 검색하는 것을 프로토타입 체이닝(prototype chaining)이라고 한다.


모든 생성자 함수는

Function.prototype

과 연결되며, 모든

__proto__

객체는

Object.prototype

과 연결된다. 즉, 이 말은 재귀적으로 계속 연결될 수 있다는 말이다. 하지만 직접적인 의미는 없고, 실제 메모리 상에서 재귀적으로 연결되어 있는 것은 아니다. 그저, 사용자가 접근하면 해당 정보를 얻을 수 있을 뿐이다.


Object.prototype

은 참조형 데이터 뿐만 아니라 기본형 데이터 조차도 프로토타입 체인을 통해 접근할 수 있는 최상위 존재이다. 따라서 객체 한정 메서드들은

Object

자체에 부여하고, 모든 데이터 타입에서 활용할 수 있는 범용적인 메서드들만

Object.prototype

에 선언될 수 있다.


단,

Object.create

를 사용하면

__proto__

가 없는 객체를 생성할 수 있다.


유사 배열 객체를 생성하는 생성자 함수의

prototype

[]

을 할당하면, Array의

prototype

과 연결시킬 수 있다.



클래스

객체지향 프로그래밍의 기반이 되는 개념이지만, JavaScript는 프로토타입 기반 언어라 ‘클래스’나 ‘상속’의 개념이 없었다. 하지만 객체지향에 익숙한 개발자들의 멘탈 모델에서 발생하는 혼란으로 ‘상속’처럼 보이기 위한 기법들이 생겨나기 시작했으며 ES6에서는 클래스 문법까지 등장하게 되었다.


용어

  • 클래스(Class)

    • 개체의 공통 속성을 모아 정의한 추상적인 개념 또는 구체적인 개체

      • 인스턴스가 사용할 메서드를 정의하는 역할일 경우에는 추상적인 개념

      • 스태틱 메서드를 사용할 때에는 구체적인 개체

    • 클래스가 먼저 정의되어야 인스턴스를 생성할 수 있다.

    • 추상성

      • 클래스를 추상적인 틀로 사용하지 않는 것은 예상치 못한 오류를 야기할 수 있다.

      • 클래스의 값은 인스턴스에 영향을 끼쳐서는 안된다.

  • 인스턴스(Instance)

    • 어떤 클래스의 속성을 지니는 실존하는 객체

    • 인스턴스를 생성할 때 사용할 수 있는 클래스는 한 개 뿐이므로 하나의 인스턴스는 단 한 개의 클래스를 바탕으로 만들어진다.


생성자 함수를 통해 생성한 인스턴스는 프로토타입 체이닝을 통해 생성자로 접근하는 것이지만, 결과적으로는 생성자 함수는 일종의 클래스가 되고,

prototype

내부 프로퍼티들이 상속된다고 볼 수 있게 된다.




Wanna get in touch?

All Icons byiconiFy