[TIL 57] javascript | Prototype

sunny·2021년 7월 4일
0
post-thumbnail

자바스크립트를 공부하면서 가장 진입장벽이 높은 개념인 프로토타입,, 🤪
하나하나 차근차근 살펴보기!


프로토타입이란

자바스크립트는 프로토타입 기반 언어이다.
클래스 기반 언어에서는 상속을 사용하지만 프로토타입 기반 언어에서는 어떤 객체를 원형으로 삼고 이를 복제함으로써 상속과 비슷한 효과를 얻는다.

Prototype은 말 그대로 객체의 원형이라고 할 수 있다. prototype이라는 프로퍼티는 그 용도가 약속되어 있는 특수한 프로퍼티다. prototype에 저장된 속성들은 생성자를 통해서 객체가 만들어질 때 그 객체에 연결된다.

어떤 생성자 함수를 new 연산자와 함께 호출하면 constructor에 정의된 내용을 바탕으로 새로운 인스턴스가 생성된다. 이때 인스턴스에는 __proto__라는 프로퍼티가 자동으로 부여되는데 이 프로퍼티는 constructor의 prototype이라는 프로퍼티를 참조한다.

예를 들어서 살펴보자!


Dog라는 함수를 만들고, Dog에 bark라는 prototype 속성을 추가해주었다.

function Dog(){}
Dog.prototype.bark = 'bow wow';

new 연산자를 통해 인스턴스를 생성했다.

const bori = new Dog();

bori를 호출해보면, __proto__라는 프로퍼티와 bark속성이 부여되어있다.


Prototype Chain

function Animal(){}
Animal.prototype.bark = true;
 
function Dog(){}
Dog.prototype = new Animal();
 
function SmallDog(){}
SmallDog.prototype = new Dog();
 
const bori = new SmallDog();
console.log(bori.bark); //true

생성자 SmallDog을 통해 만들어진 객체 bori가 Animal의 프로퍼티 bark에 접근 가능한 것은 prototype 체인으로 SmallDog과 Animal이 연결되어 있기 때문이다. 내부적으로는 아래와 같은 일이 일어난다.

  1. 객체 bori에서 bark를 찾는다.
  2. 없다면 SmallDog.prototype.bark를 찾는다.
  3. 없다면 Dog.prototype.bark를 찾는다.
  4. 없다면 Animal.prototype.bark를 찾는다.

만약, bori와 SmallDog의 bark속성을 변경하면 어떻게 될까?

function Animal(){}
Animal.prototype.bark = true;
 
function Dog(){}
Dog.prototype = new Animal();
 
function SmallDog(){}
SmallDog.prototype = new Dog();
SmallDog.prototype.bark = 'wal wal';
 
const bori = new SmallDog();
bori.bark = 'bow wow';
console.log(bori.bark); //bowwow

prototype는 객체와 객체를 연결하는 체인의 역할을 한다.
이러한 관계를 prototype chain이라고 한다.


만약!! SmallDog.prototype = Animal.prototype 으로 한 후,
SmallDog의 bark 값을 변경하면 어떻게 될까?

function Animal(){}
Animal.prototype.bark = true;
 
function Dog(){}
Dog.prototype = Animal.prototype;
 
function SmallDog(){}
SmallDog.prototype = Animal.prototype;
SmallDog.prototype.bark = 'bow wooooow';
 
const bori = new SmallDog();

SmallDog.prototype = Animal.prototype 으로 하면 안된다. SmallDog.prototype의 값을 변경하면 Animal.prototype도 변경하기 때문이다.

Dog.prototype = new Animal()은 Animal.prototype의 원형으로 하는 객체가 생성되기 때문에 new Animal()를 통해서 만들어진 객체에 변화가 생겨도 Animal.prototype의 객체에는 영향을 주지 않는다.


Prototype과 Class의 차이

es6부터 Class 문법이 추가되었다.
그렇다고 자바스크립트가 프로토타입 기반 언어에서 클래스 기반 언어가 된 것은 아니다.

class는 상속이 가능하지만 Prototype은 상속이 불가능하다.

Prototype에서 상속을 구현하고자 한다면 앞서 설명했던 prototype chaining을 사용해야한다. 그렇지만 class를 사용하면 객체 생성자로 구현했던 코드를 조금 더 명확하게 구현 할 수 있고 상속도 훨씬 쉽게 해줄 수 있기 때문에 class를 사용하면 굳이
prototype chaining 을 써야할 필요가 없다.

불변성과 가변성

class는 '틀' 과 같아서 도중에 바뀌는 일이 없다. 같은 틀 안에서 찍어낸 인스턴스를 프로퍼티나 메소드를 추가 하지 않는 이상 동일한 형태를 가진다.

반면 prototype 기반 언어는 객체가 곧 설계도가 되기 때문에 동적인 설계가 가능하다.

profile
blog 👉🏻 https://kimnamsun.github.io/

0개의 댓글