[Javascript] 생성자 함수와 프로토타입

winter100·2024년 1월 3일

자바스크립트

목록 보기
8/15

1. 생성자 함수와 프로토타입

1.1 생성자 함수

  • 클래스 말고 생성자 함수로도 클래스와 같은 효과를 얻을 수 있다
  • 객체를 생성할때 new키워드를 사용한다.
  • 관례상 첫 글자는 대문자로 시작한다.
  • 생성자 함수의 상속은 프로토타입 체인을 통해 구현한다.
  • 공통으로 사용하고자 하는 메서드가 있다면 프로토타입에 추가 해야한다.
`클래스를 이용한 객체 생성`
class Person {
  constructor(name, age){
    this.name = name;
    this.age = age;
  }
}
const person = new Person("홍길동", 20);

`생성자 함수를 이용한 객체 생성`
function Person2(name, age){
  this.name = name;
  this.age = age;
}
const person2 = new Person2("홍길동", 20);

ㄱ. 프로토타입(prototype) (DNA? 같은 존재)

(클래스와 생성자 함수에 모두 존재함)

  • 객체 지향 프로그래밍의 핵심 개념 중 하나
  • 객체 간에 메서드와 속성을 공유하는데 사용됨
  • 프로토타입 객체: 모든 함수는 prototype이라는 속성을 갖고있음
  • prototype속성은 해당 함수를 생성자로 사용하여 생성되는 모든 객체가 공유하는 객체임
  • 프로토타입 객체에 속성이나 메서드를 추가하면 해당 함수를 통해 생성된 모든 객체는 이 속성과 메서드에 접근 가능

ㄴ. __proto__

(모든 객체에는 proto라는 속성이 존재)

  • proto속성은 해당 객체가 생성될때 사용된 생성자 함수의 prototype 속성을 가리킴
  • 이렇게 생성된 객체는 생성자 함수의 prototype에 정의된 메서드와 속성을 사용할 수 있게됨.
  • 객체의 속성을 찾을때, 해당 객체에 해당 속성이 없으면 자바스크립트는 객체의 proto속성이 가리키는 프로토타입 객체에서 해당 속성을 찾음
  • 이런 프로토타입 체인의 끝(Object.prototype)에 도달할때 까지 계속됨. 이것을 프로토타입 체인이라고 함
`클래스`
class Person {
  constructor(name, age){
    this.name = name;
    this.age = age;
  }
}

`생성자 함수`
function Person2(name, age){
  this.name = name;
  this.age = age;
}

console.dir(Person)  `아래의 이미지 참고`
console.dir(Person2) `아래의 이미지 참고`

dir

  • 클래스와 생성자 함수 모두 자신의 prototype이 존재함.
  • prototype은 객체가 생성될때 해당 객체의 __proto__가 가리키는 존재가됨.

클래스와 생성자 함수의 프로토타입 차이

  • 클래스와 생성자 함수에 각각 나이를 출력하는 메서드를 입력함
  • 클래스의 메서드는 프로토타입에서 확인가능
  • 생성자 함수의 메서드는 프로토타입에서 확인 불가능
  • 클래스는 메서드를 자동으로 프로토타입에 넣어 메모리를 효율적으로 쓸수 있게 하지만,
  • 생성자 함수 내부에서 this 키워드를 사용해 메서드를 추가하면 그 메서드는 생성되는 각각의 객체에 추가되어 프로토타입에 추가 되지 않음

프로토타입


  • 생성자 함수에서 프로토타입에 넣으려면 직접 넣어줘야함
function Person2(name, age){
  this.name = name;
  this.age = age;
}

`생성자 함수에서 프로토타입에 직접 메서드를 넣어줘야함`
Person2.prototype.printAge = function(){
  console.log(this.age)
} 

console.dir(Person2) `아래의 이미지 참고`

dit


생성자 함수의 보충 설명

`생성자 함수`
function Person2(name, age){
  this.name = name;
  this.age = age;
  this.printAge = function(){
    console.log(this.age)
    }  
}
Person2.prototype.getEl = function(){console.log(1)}

console.log(Person2)
console.dir(Person2)

업로드중..

생성자 함수에서 this를 이용한 메서드

  • 생성자 함수에서 this를 이용한 메서드는 console.log에서 확인이 가능하지만 prototype에는 없음 (독립적인 메서드를 갖기때문)
  • 이 생성자 함수를 이용한 객체는 모두 독립적인 printAge메서드를 갖게 되어 메모리를 조금 더 잡아먹게됨

생성자 함수에서 prototype에 입력한 메서드

  • prototype에 직접 넣은 메서드는 console.log에는 없지만 prototype에 존재함 (DNA같은? 존재)
  • prototype에 메서드를 넣었기 때문에 해당 생성자 함수로 생성된 객체의 __proto__prototype을 참조 하고 있기 때문에 객체가 여러개 생성 되더라도 하나의 prototype을 참조하기 때문에 메모리가 절약됨.

프로토 타입 변경하기

  • Object.setPrototypeOf() 메서드를 이용해 프로토타입 변경이 가능하다
`생성자 함수로 만든 객체의 프로토타입 변경`
function Person(name, age) {
    this.name = name;
    this.age = age;
}

const person1 = new Person('홍길동', 25);

console.log(person1.sayHello()); // person1.sayHello is not a function

const newPrototype = {
    sayHello: function() {
        return '안녕하세요, ' + this.name + '입니다.';
    }
};

Object.setPrototypeOf(person1, newPrototype);

console.log(person1.sayHello());  // "안녕하세요, 홍길동입니다."

------------------------------------------------------
`생성자 함수를 이용한 다른 방식? 으로 프로토 타입 변경`
function Person(name, age) {
    this.name = name;
    this.age = age;
}

const person1 = new Person('홍길동', 25);

function newProtoType1() {}

newProtoType1.prototype.sayHello = function() {
    return '안녕하세요, ' + this.name + '입니다.';
}

Object.setPrototypeOf(person1, new newProtoType1());

console.log(person1.sayHello()); // "안녕하세요, 홍길동입니다."


------------------------------------------------------
`클래스를 이용해 만든 객체의 프로토타입 변경`
class ClassA {
    constructor(name) {
        this.name = name;
    }
}

const objA = new ClassA('홍길동');
console.log(objA.sayHello()); // objA.sayHello is not a function

class ClassB {
    sayHello() {
        return `안녕하세요, ${this.name}입니다.`;
    }
}

Object.setPrototypeOf(objA, new ClassB());

`
const objB = new ClassB();
Object.setPrototypeOf(objA, objB);
이렇게도 할 수 있으며 약간의 차이가 있다는데 알아봐야겠다.
`

console.log(objA.sayHello());  // "안녕하세요, 홍길동입니다."

0개의 댓글