프로토타입과 프로토타입 체인

July 16, 2020

프로토타입

  • 정의 : 프로토 타입 == 원형 객체의 원형을 말함
  • 자바스크립트 내에서는 유일한 생성자는 객체이다. 함수 또한 객체이기 때문이다.

프로토 타입은 언제 생길까?

  • 함수가 생성되면 함수의 Prototype이 같이 생성됨

  • Prototype 생기면서 proto 동시에 생김(프로토 타입의 부모)

    function Foo() {}
    
    let foo = new Foo()
    
    foo -
        Foo() -
        Constructor() - // 프로토타입
        __proto__ // 프로토 타입의 프로토타입 << 부모를 뜻함

프로토타입 체인은 무엇인가요?

  • 현재 객체에서 해당 변수나 메서드가 없으면 프로토타입을 확인하고 프로토타입에도 없으면 프로토타입의 프로토타입을 찾아 올라간다(체인)

  • 자바스크립트는 최상위 오브젝트는 Object이고 그 이후에는 null이기 때문에 종료조건은 proto === null 이면 종료를 하고 undefined를 리턴한다.

    let f = function () {
        this.a = 1
        this.b = 2
    }
    let o = new f() // {a: 1, b: 2}
    
    // f 함수의 prototype 속성 값들을 추가 하자.
    f.prototype.b = 3
    f.prototype.c = 4
    
    console.log(o.z) // undefiend
    
    // 1. f() 생성자의 프로퍼티 확인
    // 2. 없다면 f().prototype 확인
    // 3. 없다면  f().prototype.prototype 확인
    // 4. 상위 프로토타입까지 찾고 null이면 undefined를 리턴한다.

클래스 문법은 프로토 타입과 다르게 상속으로 이루어져 있지 않나요?

  • 결론을 말하자면 자바스크립트는 프로토타입으로 구현한 상속을 구현한 것이지 자바처럼 상속을 지원하지 않는다(단순한 문법설탕 같은거)

  • 자바스크립트로 구현할 수 있는 상속은 총 3가지 위임형 상속, 연결형 상속, 함수형 상속이 있다.

  • 위임형 상속 : 프로토타입에 함수를 정의하여 메모리를 절약할 수 있다. 단점은 프로토타입이 변경되면 모든 메소드가 변경되어 위험하다.

    class Greeter {
        constructor(name) {
            this.name = name || 'John Doe'
        }
        hello() {
            return `Hello, my name is ${this.name}`
        }
    }
    
    const george = new Greeter('George')
    const msg = george.hello()
    console.log(msg) // Hello, my name is George
  • 연결형 상속 : 프로토타입을 인용하는게 아니라 protytype을 꺼내어 하나의 객체를 만드는 것이다.

    const proto = {
        hello: function hello() {
            return `Hello, my name is ${this.name}`
        },
    }
    
    const george = Object.assign({}, proto, { name: 'George' })
    const msg = george.hello()
    console.log(msg) // Hello, my name is George
  • 함수형 상속 : 기존 객체를 확장 시키며, 클로져를 통해 구현

    const rawMixin = function () {
        const attrs = {}
        return Object.assign(
            this,
            {
                set(name, value) {
                    attrs[name] = value
                    this.emit('change', {
                        prop: name,
                        value: value,
                    })
                },
                get(name) {
                    return attrs[name]
                },
            },
            Events.prototype
        )
    }
    
    const mixinModel = (target) => rawMixin.call(target)
    const george = { name: 'george' }
    const model = mixinModel(george)
    model.on('change', (data) => console.log(data))
    model.set('name', 'Sam')
    /*
      {
        prop: 'name',
        value: 'Sam'
      }
      */

static 문법은 무엇인가요?

  • 인스턴스 없이 호출이 가능한 함수 주로 유틸함수에 많이 사용된다.

    class Hello {
        static foo() {
            console.log('hello static')
        }
    }
    
    Hello.foo() // hello static
    
    let bar = new Hello()
    
    bar.foo() // uncatch typeErrors

© 2023, Customized by Joon