function Work(indicator) {
this._indicator = indicator ?? 0;
}
Work.prototype.start = function () {
setInterval(() => {
this._indicator += 10;
this._draw();
}, 1000);
}
Work.prototype._draw = function () {}
function WorkA() { Work.call(this, 0); }
WorkA.prototype = Object.create(Work.prototype, {});
WorkA.prototype._draw = function () { /* linear progress drawing logic */ };
function WorkB() { Work.call(this, 10); }
WorkB.prototype = Object.create(Work.prototype, {});
WorkB.prototype._draw = function () { /* linear progress drawing logic */ };
const workA = new WorkA();
const workB = new WorkB();
workA.start();
workB.start();
💡 이번 페이지에서 우리는 Javascript 프로토타입 개념에 대해 복기하는 시간을 가져보자.
https://youtu.be/yXnbvyl04V4?si=ARe7eejhO-lWQitT
https://youtu.be/673mZ8rE9UY?si=u8xcqzDIeavjBpLl
자바스크립트의 프로토타입 개념이 생소하다면 위 영상을 통해 개념을 한번 짚고 넘어가자 프로토타입은 무엇인지, 프로토타입 체이닝은 어떤 개념인지 살펴보실 수 있다.
프로토타입이란?
- 자바스크립트는 프로토타입 기반 언어이다. 즉, 객체를 생성할 때, 그 객체는 자신의 부모 역할을 하는 프로토타입 객체를 가르키는 [[Prototype]]라는 내부 슬롯을 갖는다. 클래스 처럼 객체의 인스턴스를 위한 명세와 같은 역할을 하는데 객체 본인만이 가진 속성과 메서드에도 접근할 수 있으면서 프로토타입에도 접근할 수 있다.
function Person() {}
// new 키워드로 함수를 호출할 때 마다 생성되는 인스턴스는 함수 프로토 타입의 모든 속성을 상속한다
let person1 = new Person();
console.log(Person.prototype === person1.__proto__);
위 코드에서 Person.prototype은 Person 함수를 통해 생성된 객체의 부모 역할을 하는 프로토타입 객체이다. person1.__proto__는 person1 객체의 부모 역할을 하는 프로토타입 객체를 가르킨다. 따라서 Person.prototype과 person1.__proto__는 같은 객체를 가르킨다.
네이티브 객체 프로토타입
- 자바스크립트의 Array, String 등의 내장 객체 역시 자신의 프로토타입을 가지고 있다
- 배열을 선언해 늘 사용하던 map, filter 등을 사용해 조작하고 문자열을 선언해 split 등의 연산을 할 수 있게 해주는 이유이다
const arr = [1,2,3,4,5];
console.log(Object.getPrototypeOf(arr)) //Array prototype
const str = "Hello world!";
console.log(Object.getPrototypeOf(str)) //String prototype
const date = new Date();
console.log(Object.getPrototypeOf(date)) //Date prototype
프로토타입 체이닝
- 프로토타입 체이닝은 객체의 속성을 참조하거나 메서드를 호출할 때, 해당 객체에 해당 속성이나 메서드가 없다면[[Prototype]]이 가리키는 링크를 따라 자신의 부모 역할을 하는 프로토타입 객체의 속성이나 메서드를 참조하거나 호출하는 것을 의미한다. 즉, 다른 객체에서 정의된 메서드와 속성을 한 객체에서 사용할 수 있게 해준다.
function Person() {}
Person.prototype.sayHello = function() {
console.log('Hello');
};
let person1 = new Person();
person1.sayHello(); // Hello
위 코드에서 person1 객체는 sayHello라는 메서드를 갖고 있지 않지만, Person.prototype이라는 프로토타입 객체가 sayHello 메서드를 갖고 있다. 따라서 person1.sayHello()를 호출할 때 프로토타입 체이닝이 발생하여 Person.prototype의 sayHello 메서드가 호출한다.
이처럼 프로토타입과 프로토타입 체이닝을 통해 JavaScript는 객체 간 상속과 메서드 재사용을 가능하게 한다.
new 키워드를 사용할 때 발생하는 내부동작에 대해 조금 더 궁금증이 생긴다면 Javascript Variable Object라는 키워드를 찾아보자.
프로토타입을 사용하는 이유
- 메모리 효율
- 자바스크립트에서 모든 객체는 프로토타입을 공유한다. 객체 자체가 스스로 메서드와 속성을 모두 가지는 대신 여러 객체가 동일한 프로토타입을 공유하도록 하고 이를 사용하면 매모리를 효율적으로 사용할 수 있다.
- 객체지향스러움
- 프로토타입을 통해 클래스에서 상속해 사용하는 것 처럼 다른 객체로부터의 속성과 메서드를 사용할 수 있다. 이를 통해 코드 재사용이 가능해진다
- 생산성
- 프로토타입을 통해 동일한 속성, 동작이 필요한 여러 객체들마다 이를 직접 선언하고 개발할 필요 없이 프로토타입을 이용해 관리할 수 있다.
요약
- prototype은 객체 생성자 함수에 의해 생성되는 객체들이 공유하는 속성과 메소드를 저장하는 특수 객체이다.
- 모든 javascript 객체는 선언 할당하면 해당 생성자 함수의 prototype객체와 연결되며 프로토타입 체이닝을 통해 해당 객체의 속성, 메소드에 접근 가능하다.
참고문서
'Front-End > JavaScript' 카테고리의 다른 글
Vanilla JavaScript로 React Hooks 구현하기 (0) | 2024.03.25 |
---|---|
[JavaScript] Map Object (맵) (0) | 2022.04.03 |
[JavaScript] this란? (0) | 2022.03.13 |
[JavaScript] Closure (클로저) (0) | 2022.03.09 |
[JavaScript] var / let / const 변수 (0) | 2022.03.09 |