-
[Javascript] 프로토타입(Prototype)?Front-end/Javascript 2020. 7. 19. 21:33반응형
들어가기 전에, prototype
자바스크립트로 개발을 해보았다면, 대부분의 개발자들은 prototype이라는 것을 마주쳤을 것이다.
Prototype의 존재와 역할이 무엇인지 궁금하지 않을 수도 있지만, 대부분 이직 또는 취업 준비할 때 다시 만나게 될 것이다.
흐릿해진... 아주 흐릿해진 개념을 살리기 위해 다시 공부하기로 했다.
(잠깐!) 자바스크립트는 객체지향인가?
나 또한, 이번 공부를 하기 전에는 자신있게 누군가에게 설명해줄 수는 없었다.
자바스크립트는 흔히 프로토타입 기반 프로그래밍이라고 한다.
위키백과에 따르면 프로토타입 기반 프로그래밍은 객체지향 프로그래밍의 한 형태의 갈래로 클래스가 없고, 클래스 기반 언어에서 상속을 사용하는 것과는 다르게, 객체를 원형(프로토타입)으로 하여 복제의 과정을 통해 객체의 동작 방식을 다시 사용할 수 있다. 프로토타입 기반 프로그래밍은 클래스리스(class-less), 프로토타입 지향(prototype-oriented) 혹은 인스턴스 기반(instance-based) 프로그래밍이라고 한다.
ECMA6(ES2015)에서 자바스크립트에도 Class가 문법적인 양념일 뿐이며, 자바스크립트는 여전히 기존의 객체를 복사하여(cloning) 새로운 객체를 생성하는 프로토타입 기반의 언어이다.
요약을 해보자면, 자바스크립트는 OOP의 한 갈래이지만, class-less인 프로토타입 기반의 방법론(?)이다.
우리가 간과했던 함수와 객체의 구조
우리는 클래스와 유사하게 프로토타입 형태의 코드를 써왔다.
아래 코드처럼 Car이라는 함수를 선언하게 되면, 그림1과 같은 형태의 관계가 생겨나게 된다.
function Car(){}
그림1. Car함수와 Car프로토 타입 객체의 관계도 Car 프로토타입 객체처럼 constructor이 있으면 new를 통해 객체를 만들어 낼 수 있게 된다.
그림1에서 한가지 더 발견할 수 있는 것은 Car의 __proto__(후에 설명)는 Object 프로토타입 객체가 있다. 그리고 이것의 constructor은 Object() 함수이며, __proto__는 존재하지 않는다(null). 이후에 설명할 것이지만, 모든 프로토타입 객체의 끝은 Object이다.
function Car() {} var mini = new Car() var avante = new Car()
그림2. mini, avante 객체와 Car 프로토타입 객체의 관계 Car 함수의 prototype 속성이 참조하는 Car 프로토타입 객체(Prototype Object)는 var mini = new Car()처럼 new 연산자와 Car 함수를 통해 생성된 모든 객체의 원형이 되는 객체가 된다. 이쯤되면 프로토타입 객체가 무엇인지 궁금해진다.
Property Object (프로토타입 객체), Prototype Link(프로토타입 링크)
함수를 정의하면 생성되는 프로토타입 객체는 자신이 new와 함수를 통해 생성되는 다른 객체의 원형이 된다. 그리고 그림2에서의 Car 프로토타입 객체 박스를 보면, 기본적으로 constructor와 __proto__를 가지고 있다. 모든 객체는 프로토타입 객체에 접근할 수 있습니다. 프로토타입 객체도 일반적인 객체이므로 동적으로 런타임에 속성을 마음대로 추가할 수 있다. 같은 원형을 복사로 생성된 모든 객체(mini, avante)는 추가된 속성을 사용할 수 있다.
function Car() {} var mini = new Car() var avante = new Car() Car.prototype.wheel = 4 console.log(mini.wheel) console.log(avante.wheel)
그림3. 동적할당된 프로토타입 객체의 wheel 변수 여기서 사용되는 개념이 프로토타입 체인을 이용한 상속이다.
자바스크립트 객체는 속성을 저장하는 동적인 "가방"과 (자기만의 속성이라고 부른다) 프로토타입 객체에 대한 링크(__proto__)를 가진다. 객체의 어떤 속성에 접근하려할 때 그 객체 자체 속성 뿐만 아니라 객체의 프로토타입, 그 프로토타입의 프로토타입 등 프로토타입 체인의 종단에 이를 때까지 그 속성을 탐색한다.
즉, mini와 avante에서 wheel 속성은 선언되어있지 않았기 때문에, __proto__(프로토타입 객체에 대한 링크)를 통해서 Car 프로토타입 객체에서 wheel을 찾는다. 다른 예시로, mini.doorType을 찾게 되면, mini, Car 프로토타입에 존재하지 않기 때문에, Car 프로토타입의 __proto__를 타고 Object 프로토타입 객체까지 체이닝을 사용하게 된다. 여기서 존재하지 않기 때문에 undefined를 표시할 것이다.
마무리
호이스팅과 컨텍스트 개념에서 사용한 Scope Chain이 생각나는 개념이었다.
Javascript는 프로토타입 프로그래밍을 기반하여 만들어졌다. Class가 아닌 Prototype을 통해 캡슐화, 메모리 최적화 등을 할 수 있도록 잘 활용해야할 것으로 보인다.
p.s Object.prototype 혹은 빌트인 프로토타입의 확장은 종종 이용되지만 오용이다. 사용하지 말자!
참고
MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/applyko.wikipedia.org/wiki/프로토타입_기반_프로그래밍
오승환님 medium: https://medium.com/@bluesh55/javascript-prototype-이해하기-f8e67c286b67
NexTree: http://www.nextree.co.kr/p7323/
Wiki: https://www.zerocho.com/category/JavaScript/post/57433645a48729787807c3fdko.wikipedia.org/wiki/프로토타입_기반_프로그래밍반응형'Front-end > Javascript' 카테고리의 다른 글
[Javascript] ES12 ES2021? (0) 2020.12.08 [Javascript] 쓰로틀링, 디바운싱(throttling, debouncing)? (0) 2020.07.26 [Javascript] call, apply, bind? (0) 2020.06.16 [Javascript] async & await? (0) 2020.06.14 [Javascript] sort() 함수의 함정 (0) 2020.05.17