ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JavaScript - Prototype & Prototype chain (프로토타입과 프로토타입 체인)
    내가 보기 위해 쓰는 것/Javascript 2019. 10. 24. 11:24

    프로토타입은 이럴 때 필요하다.

    예를 들어 자동차라는 객체를 정의한다고 가정해보자.

     

    function Car (name,maxSpeed,n) {
        this.name = name
        this.maxSpeed = maxSpeed
        this.currentSpeed = 0
        this.speedUp = () => {
          this.currentSpeed += n
        }
        this.speedDown = () => {
          this.currentSpeed -= n
        }
    }
    

     

    정상적으로 작동할 것이다. 그런데 문제가 있다.

    만약 Car 객체가 아주 많다면 어떻게 될까?

    모든 Car 객체가 speedUp, speedDown 기능을 내장할 것이다. 모든 Car객체가 같은 기능을 중복으로 가지고 있는 것이다. 즉 메모리 낭비다.

     

    그렇기 떄문에 prototype 기능이 필요하다.

     

    prototype = 객체 원형

     

    모든 객체가 공유하는 값, 함수등을 지정 하는 것이다.

    이 기능을 사용하면 중복된 값, 함수를 원형에 하나만 지정하여 메모리 효율도 높이고 당신의 코드를 더 fency하게 만들 수 있다 ^^_^_^

     

    prototype을 사용한 방식으로 바꿔보자.

     

    function Car (name, maxSpeed) {
        this.name = name
        this.maxSpeed = maxSpeed
        this.currentSpeed = 0
    }
    
    Car.prototype.speedUp = function (n) {
      this.currentSpeed += n
    }
    
    Car.prototype.speedDown = function (n) {
      this.currentSpeed -= n
    }
    

    이렇게 하면 모든 car객체가 speedUp, speedDown을 가지지 않고 Car객체의 원형에서 함수를 빼오는 방식이 된다.

    내가 쓴 예제에서는 함수로만 예를 들었지만 당연히 변수도 된다. 그러니 공통의 값을 가지는 변수는 prototype으로 지정 할 수 있다.

     

    프로토타입의 사용 방법은 이렇게 간단하지만, 아직 하나 더 언급해야할 것이 있다.

    프로토타입 체인이다.

     


     

    프로토타입 체인은 사용방법이 있는 기능이 아니라 객체 자체에 내장되어있는 기능이다.

    기본적인 개념은 이렇다.

     

    객체의 속성이나 메소드를 호출 할 때, 자신에게 해당 멤버가 있는지 찾아 본 다음, 프로토타입에서 객체에서 멤버를 찾는다.
    찾는 속성이나 메소드를 찾을 떄 까지 프로토타입 체인을 타고 올라간다.

     

    위에서 쓴 예제를 이용해서 가장 간단한 프로토타입 체인이 적용되는 예를 보자.

     

    
    function Car (name, maxSpeed) {
        this.name = name
        this.maxSpeed = maxSpeed
        this.currentSpeed = 0
    }
    
    Car.prototype.speedUp = function (n) {
      this.currentSpeed += n
    }
    
    Car.prototype.speedDown = function (n) {
      this.currentSpeed -= n
    }
    
      let cars = new Car ('myCar', 300)
      console.log(cars.currentSpeed)
      cars.speedUp(10)
      console.log(cars.currentSpeed)
      cars.speedUp(10)
      console.log(cars.currentSpeed)
      cars.speedDown(10)
      console.log(cars.currentSpeed)
    
    
    

     

    위 소스의 결과

     

    여기서도 사실 프로토타입 체인의 개념이 적용되었다.

     

    하단 실행부를보면 cars.speedUp, speedDown을 호출하고 있다.

    그리고 cars 자체가 speedUp, speedDown 이라고 멤버를 정의 한 것이 아니라 prototype에서 정의 했다.

    즉 cars 본인이 가지고 있는 멤버에서 speedUp speedDown이 있나~ 둘러본 후 없으니까

    prototype을 타고 올라가서(chain) 멤버를 찾아보고는 있구만 하고 사용한 것이다.

     

    잠깐! 이 글에서는 prototype 하나만 알려줬는데 '찾을 때까지 타고 올라간다' 라면 prototype 위에 뭔가 더 있다는 거 아님?? 

     

    맞다. 더 있다. 바로 Object 객체다.

     

    prototype을 타고타고 올라가다보면 최종적으로 모든 객체의 부모가 되는 Object 객체가 있다.

     

    프로토타입 체인을 이용해 Object 객체의 멤버에 접근해보자.

     

    function Car (name, maxSpeed) {
        this.name = name
        this.maxSpeed = maxSpeed
        this.currentSpeed = 0
    }
    
    Car.prototype.speedUp = function (n) {
      this.currentSpeed += n
    }
    
    Car.prototype.speedDown = function (n) {
      this.currentSpeed -= n
    }
    
      let cars = new Car ('myCar', 300)
      console.log(cars.currentSpeed)
      cars.speedUp(10)
      console.log(cars.currentSpeed)
      cars.speedUp(10)
      console.log(cars.currentSpeed)
      cars.speedDown(10)
      console.log(cars.currentSpeed)
      console.log(cars.toString())
    

     

    마지막 줄에 cars.toString 이라는 정의한 적 없는 메소드를 호출했다.

     

    [object Object]를 반환했다.

    정의 하지 않은 메소드인데 무언가를 반환하고 있다. 바로 Object가 가지고 있는 멤버를 찾아간 것이다.

     

    cars한테 toString이 없다 > cars.prototype에도 없다 > Object한테 toString이 있다.

     

    그러니까 프토토타입은 최종적으로 모든 객체의 부모가 되는 Object라는 객체를 찾아가게 된다.

    Object객체가 가지고 있는 멤버는 이렇다.

    속성/메소드 설명
    constructor

    속성으로 생성자 함수를 가리킨다.

    var d = new Date()

    d.constructor는 Date()와 같다.

    valueOf() 메소드로서 객체를 숫자로 변환한다.
    toString() 메소드로서 객체의 값을 문자열로 변환한다.
    hasOwnProperty() 전달 인수로 주어진 속성을 가지고 있으면 true 반환
    isPrototypeOf() 현재 객체가 전달 인수로 주어진 객체의 프로토타입이면 true 반환

     

    간략하게 프로토타입과 프로토타입 체인에 대해서 정리해보았다.

     

    자세한 내용을 더 보고싶다면 이 문서를 추천한다.

     

    상속과 프로토타입

    Java 나 C++ 같이 클래스 기반의 언어를 사용하던 프로그래머는 자바스크립트가 동적인 언어라는 점과 클래스가 없다는 것에서 혼란스러워 한다. (ES2015부터 class 키워드를 지원하기 시작했으나, 문법적인 양념일 뿐이며 자바스크립트는 여전히 프로토타입 기반의 언어다.)

    developer.mozilla.org

     

    댓글

Designed by Tistory.