alt
Home 모던 JavaScript 튜토리얼 - Prototype
Post
Cancel

모던 JavaScript 튜토리얼 - Prototype

: 자바스크립트는 프로토타입 기반 언어이다. 모든 객체들클래스로 정의해놓은 메소드와 속성상속받기 위한 템플릿으로써 프로토타입 객체를 가진다.


Prototype

: 모든 객체들이 클래스의 정보들을 상속받을 수 있도록 템플릿 역할을 수행한다.


  • 기본적으로 Class로 객체를 정의한다고 해도 자바스크립트 내부적으로는 프로토타입으로 관리된다.

  • ES2015 클래스 구문으로 조금더 편리하게 볼 수 있도록 제공하는것

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    class Person {
        constructor(name, age) {
            this.name = name;
            this.age = age;
        }
          
        getName() {
            return this.name;
        }
    }
      
    // ---------------------- 위의 방식으로 class를 선언한다고해도 사실은 아래와같이 관리됨
      
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
      
    Person.prototype.getName = function() {
        return this.name;
    }
    


함수의 prototype 프로퍼티와 프로토타입 객체의 constructor 프로퍼티

1
2
3
4
5
6
7
function Rabbit(name) {
    this.name = name;
}
// 기본 prototype
// Rabbit.prototype = { constructor: Rabbit };

let rabbit = new Rabbit("white rabbit");
  • 위와같은 줄을 그림으로 표현하면 아래와 같다.

image-20210910172442530

  • Rabbit 함수에서는 Rabbit.prototype과 같이 Rabbit 프로토타입 객체로 접근 가능

  • Rabbit 프로토타입 객체에서는 constructur 속성은 Rabbit 함수를 참조한다.

  • getName(), setName() 같은 프로퍼티들이 Rabbit 함수에 추가가 되면 프로토타입에 해당 프로퍼티를 유지한다.

    • 따라서, 새로 만든 인스턴스들은 프로토타입 원형을 복사해 사용한다.
    1
    2
    3
    4
    5
    6
    7
    8
    
    function Rabbit(name) {
      this.name = name;
      alert(name);
    }
      
    let rabbit = new Rabbit("White Rabbit");
      
    let rabbit2 = new rabbit.constructor("Black Rabbit");
    
    • 위와같은 경우 rabbit 객체의 constructor로 Rabbit 함수에 접근하는 것


자바스크립트는 알맞은 constructor 값을 보장하지 않는다.

1
2
3
4
5
6
7
function Rabbit() {}
Rabbit.prototype = {
  jumps: true
};

let rabbit = new Rabbit();
alert(rabbit.constructor === Rabbit); // false
  • 위처럼 기본 prototype 값을 다른 객체로 바꾸면 이 객체에는 contructor가 없을 것..


깊이 이해하기


  • 아래와같은 코드를 베이스로 변경하는 경우의 시나리오를 알아보기
1
2
3
4
5
6
7
8
function Rabbit() {}
Rabbit.prototype = {
  eats: true
};

let rabbit = new Rabbit();

alert( rabbit.eats ); // true


이미 만들어진 객체에 대해서는 영향을 주지 않는다 .

1
2
3
4
5
6
7
8
9
10
function Rabbit() {}
Rabbit.prototype = {
  eats: true
};

let rabbit = new Rabbit();

Rabbit.prototype = {}; // add this line

alert( rabbit.eats ); // true


Rabbit.prototype이 참조하는 객체는 하나뿐이기 때문에 참조를 통해 객체 내용을 변경하면 다른 참조를 통해서도 변경 내용을 볼 수 있다.

1
2
3
4
5
6
7
8
9
10
function Rabbit() {}
Rabbit.prototype = {
  eats: true
};

let rabbit = new Rabbit();

Rabbit.prototype.eats = false; // add this line

alert( rabbit.eats ); // false


객체의 프로퍼티를 제거해도 따로 변화가 없다. 그러나, 객체가 참조하는 prototype 객체를 변경하면 달라진다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Rabbit() {}
Rabbit.prototype = {
  eats: true
};

let rabbit = new Rabbit();

delete rabbit.eats;

alert( rabbit.eats ); // true

delete Rabbit.prototype.eats;

alert( rabbit.eats ); // undefined
  • 만약 rabbit에서 eats를 재정의해서 사용하고 있고, 그 때 rabbit.eats를 건드리면 그 객체의 프로퍼티가 변경 될 것


시나리오로 이해하기

1
2
3
4
5
6
7
8
9
function User(name) {
  this.name = name;
}
User.prototype = {}; // (*)

let user = new User('John');
let user2 = new user.constructor('Pete');

alert( user2.name ); // undefined
  1. new user.constructor('Pete')user에서 constructor를 찾는데 아무것도 찾지 못한다.
  2. 객체에서 원하는 프로퍼티를 찾지 못했기 때문에 프로토타입 객체에서 검색을 한다. user의 프로토타입은 User.prototype인데, User.prototype은 빈 객체이다.
  3. User.prototype은 일반 객체 {}이고, 일반 객체의 프로토타입은 Object.prototype이다. Object.prototype.constructor == Object이므로 Object가 사용된다.



Reference)

모던 JavaScript 튜토리얼 https://ko.javascript.info

Node.js 디자인패턴

This post is licensed under CC BY 4.0 by the author.