[JS] 프로토타입(Prototype) #1

김민규·2022년 8월 3일
0

자바스크립트

목록 보기
4/7
post-thumbnail

참고한 페이지

Prototype

객체가 메소드, 속성을 확장받기 위한 템플릿입니다. 프로토타입에 속성과 메서드들을 정의하고 이를 받아 확장하여 쓰는 것이죠.

Chain

여기 person 객체가 하나 있습니다.

const person = {
  name: 'Jason',
  greet() {
    console.log(`Hello, I'm ${this.name}`);
  }
}

person.greet();

객체는 name 속성과 greet 메서드를 가집니다. 콘솔에 person.이라고 입력하면 다음과 같이 뜨는 것을 볼 수 있죠.

name, greet외 다른 것들이 보이는데, 이들이 바로 프로토타입에서 확장 받은 것들 입니다.

프로토타입에 접근하려면 [[prototype]]이 아닌 __proto__으로 접근합니다. 또는 Object.getPrototypeOf 메서드로 프로토타입을 얻을 수 있습니다.

모든 자바스크립트 객체는 [[prototype]]이라는 내장 객체를 가집니다. 이 내장 객체도 [[prototype]] 객체를 가지죠. 이것을 체인이라고 합니다. [[prototype]]이 null이면 체인은 끝납니다.

person.toString();
  1. toString 메서드를 person에서 찾지만 실패합니다.
  2. 프로토타입에서 toString을 찾아 실행합니다.

모든 객체의 프로토타입이 Object.prototype은 아니다

대표적인 예로 Date가 있습니다.

const now = new Date();

now의 프로토타입은 뭘까요? Date.prototype입니다. Date.prototype의 프로토타입은 Object.prototype이죠.

now.getFullYear();

getFullYear는 now의 메서드가 아닙니다. now의 프로토타입, Date.prototype의 메서드죠.

Shadowing

프로토타입에 정의된 속성과 같은 이름의 속성을 객체에 정의하면 어떻게 될까요?

const now = new Date();
console.log(now.getFullYear()); // 2022

now.getFullYear = function() {
  console.log('getFullYear');
}
console.log(now.getFullYear()); // getFullYear

프로토타입 메서드가 아닌 객체에 정의한 메서드가 호출됩니다. 이를 Shadowing이라고 합니다.

프로토타입 만들기

1. Object.create

프로토타입 객체를 정의하고 이를 프로토타입으로 하는 새로운 객체를 만듭니다.

const personPrototype = {
  greet() {
    console.log('Hello!');
  }
};

const carl = Object.create(personPrototype);
carl.greet(); // hello!

2. constructor

생성자 함수는 이름이 prototype인 속성을 가집니다. 이 prototype은 constructor 속성을 가지고 있는데, 생성자 함수 자신을 가리키고 있죠.

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

생성자 함수를 호출하면, 새 객체가 만들어집니다. 이 객체의 프로토타입이 바로 Person의 prototype입니다.

const jason = new Person('Jason');

Person의 prototype에 속성을 추가하려면 Object.assign을 사용합니다.

const personPrototype = {
  greet() {
    console.log(`Hello, I'm ${this.name}!`);
  }
};

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

Object.assign(Person.prototype, personPrototype);

직접 넣어주는 방법도 있습니다.

Person.prototype.greet = personPrototype.greet;

이제 생성자 함수로 만든 객체가 인사를 할 수 있습니다.

const sam = new Person('Sam');
sam.greet(); // Hello, I'm Sam!

여기서 명심할 것은, name은 sam의 속성이고 greet는 프로토타입의 메서드라는 것입니다. Object.hasOwn 메서드를 통해 sam의 속성인지 여부를 확인 가능합니다.

Object.hasOwn(sam, 'name'); // true
Object.hasOwn(sam, 'greet'); // false

profile
점점 더 좋아지고 있습니다

0개의 댓글