티스토리 뷰

[프로토타입 연장되는 내용입니다.]

1. 13. 프로토타입 기반 객체지향 프로그래밍 이해하기

2. 14. 프로토타입 2탄 - 메소드 오버라이딩, 오버로딩, 섀도잉

 

 

"프로토타입 교체를 통해 객체간의 상속관계를 동적으로 변경하는 번거로울 뿐만 아니라 안전하지 않기 때문에 추천하지 않습니다.

따라서 직접 상속을 하거나, es6에 도입된 클래스문을 활용해 훨씬 쉽고 직관적인 상속을 구현하는걸 지향합시다." 


프로토타입의 교체

생성자함수와 함께 생성되는 .prototype 프로퍼티는 개발자에 의해 임의의 다른 객체로 변경될 수 있습니다.

이러한 특징을 활용해서 객체간의 상속 관계를 동적으로 변경할 수 있습니다.

 

예시를 보겠습니다.

function Person(name) {
  this.name = name;
}

Person.prototype.cook = function (menu) {
  console.log(`${this.name}가 ${menu}요리를 합니다.`);
};

Person 객체의 prototype에 cook을 하면 아래와 같이 출력됩니다.

 

 

이때 Person.prototype 메소드에 다른 값을 할당하면 어떻게 될까요?

Person.prototype = { 
	sayHello() { 
    	console.log(`Hello i'm ${this.name}`); 
    }
}

sayHello의 메소드를 가진 객체가 출력되는 것을 볼 수 있습니다.

Person생성자함수의 prototype은 할당된 객체를 가리키게 됩니다. 

새로 할당된  Person.prototype에는 constructor가 없는게 보이시나요? 객체를 가리킬 뿐 객체의 역할이 바뀐다거나, constructor가 생성되는 등의 변화는 없습니다. 서로를 가리키지는 않습니다. 이는 연결이 끊어진 프로토타입입니다.

 

 


여기서 주의하실 점! 

prototype을 변경하기 이전에 생성된 객체 인스턴스들과 이후에 생성하는 객체 인스턴스들은 다른 prototype를 가지게 됩니다.

이유는 객체 인스턴스가 생성될 때 prototype이 저장되어있는 힙주소가 할당되고, Person의 prototype이 변경되면 변경된 prototype의 힙주소는 Person.prototype에만 할당되고, 이전에 생성된 객체 인스턴스들에게는 따로 재할당이 되지않습니다. 

 

예시를 함께 보시죠

function Person(name) {
  this.name = name;
}

Person.prototype.cook = function (menu) {
  console.log(`${this.name}가 ${menu}요리를 합니다.`);
};

const mom = new Person("엄마");

 Person 생성자함수를 만들고, Person.prototype에 cook 메서드를 등록했습니다. 

그 후 mom 객체 인스턴스를 생성했습니다.

 

mom.cook("김치찌개")

mom객체 인스턴스는 cook 메서드를 사용 가능합니다.

 

 

그 다음 Person.prototype을 임의의 객체로 변경해보겠습니다.

그리고 cookie 객체 인스턴스를 생성해보았습니다.

Person.prototype = {
    sayHello() {
      console.log(`Hello i'm ${this.name}`);
    },
  };

const cookie = new Person('쿠키');

person.prototype에  다른 객체를 할당하고, cookie 객체 인스턴스를 생성하게 되면 아래와 같은 결과를 확인하실 수 있습니다. 

cookie.sayHello()

 

Person과  mom과 cookie의  prototype을 확인하면 아래와 같이 출력됩니다.

 

 


 

constructor를 연결해주는 방법

연결이 끊켜있는 prototype에 constructor를 다시 연결해줄 수 있습니다.

이때 연결해주는 것은, 해당 객체에 추가해주는 것으로 이전에 작성된 prototype을 가져오는 것은 아닙니다. 연결되어 있는 객체에 constructor 프로퍼티를 할당해주는 것입니다.

Person.prototype.constructor = Person;

cookie는 cook을 새로 정의해 할당해주지 않는 한 요리를 할 수 없는거죠.. 

 

 


 

인스턴스에 의한 프로토타입 교체

Object.setPrototypeOf 메서드를 활용해 객체 인스턴스의 프로토타입을 교체할 수 있습니다. 

이는 객체 인스턴스의 __proto__으로 접근이 가능한 객체의 프로토타입을 교체하는 작업으로, 객체를 생성한 생성자함수의 prototype에는 영향이 없습니다. 

function Person(name) {
  this.name = name;
}

Person.prototype.cook = function (menu) {
  console.log(`${this.name}가 ${menu}요리를 합니다.`);
};

const mom = new Person("엄마");

const cookie = new Person('쿠키');

const otherPrototype = {
  sayHello() {
    console.log(`Hello i'm ${this.name}`);
  },
};
Object.setPrototypeOf(cookie, otherPrototype);

cookie.sayHello();

 

 

 


instance of 연산자 

객체 instanceof 생성자함수

instanceof는 객체가 프로토타입 체인상에 전달한 생성자 함수가 존재하는지 확인할 수 있게 해줍니다.

반환값으로는 true/false가 반환됩니다.

 

 


정적 프로퍼티 메서드

정적 메서드나 정적 프로퍼티는 Static으로 표현되며, 생성자 함수의 인스턴스를 만들지 않아도 사용할 수 있는 프로퍼티나 메서드를 뜻합니다. 생성자함수에 등록이 되고, 생성자 함수를 통해 사용이 가능합니다.

이는 생성자함수의 prototype에 등록하는 것과 다르게 생성자함수에 직접적으로 연결된 프로퍼티이며, 사용할 때에는 객체 인스턴스를 사용하는 것처럼이 아닌 생성자 함수를 활용해 호출하게 됩니다.

function Person(name) {
  this.name = name;
}

Person.verson = 2022;

Person.prototype.cook = function (menu) {
  console.log(`${this.name}가 ${menu}요리를 합니다.`);
};

const mom = new Person("엄마");

생성자함수에 등록된 프로퍼티로 mom에서는 조회가 되지 않습니다. verson은 생성자 함수에 직접적으로 연결된 프로퍼티입니다.

 

 

 


 

 

 

자바스크립트 프로토타입의 원리에 대해 배우는 시간이 되었습니다.

'어떻게 될까?'가 꼬리에 꼬리를 물어서 '이게 되네..'까지 왔다갔다 하다보니 생각보다 긴 시간을 들여 작성했네요.. 3탄까지..

(끊어진 생성자함수의 prototype이  Person.prototype = mom.__proto__; 로 에러없이 할당이 되는 것을 봤을 때의 놀라움이란..) 

자바스크립트 프로토타입으로 정말 변태같은 코드도 작성이 가능하겠구나 알게 되었습니다.. 너무 신기하네요 ㅎㅎ

1회 메모리부터 차근차근 배워온 내용이 모두 연결이 되어있다는게 신기하고,

자바스크립트 프로토타입의 동작을 예제와 이미지로 보니 코드를 작성할 때 어떻게 작동하게 될지 예상함에 있어서 큰 도움이 될 것 같습니다. 

:) 팀러버덕 스터디 화이팅!! 행복한 코딩라이프되세요~~! 

 

JavaScript 스터디 팀 러버덕과 함께 합니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함