Javascript(JS)도 기본적으로 객체지향언어이나, 프로토타입 기반 언어로써, 대표적인 class기반 언어인 java와 다른 특징을 가지고 있다. class 기반 언어와 프로토타입 기반 언어의 차이점은 후에 별도로 정리할 예정이며, 이번엔 프로토타입 기반 언어가 어떤 특징을 가지고 있는지 공부한 부분을 정리해 보려 한다.
특징 1. 생성자 안에서 메서드를 정의하는 방식
JS는 생성자 함수로 객체를 생성한 다음에, 안에 모든 메서드를 입력할 수 있다.
다른 언어에서는 class가 존재하지만, 자바스크립트에서는 생성자함수가 이를 대처한다. 대문자로 시작하게 된다. 그러고 new라는 키워드를 통해서 자동차 객체를 생성할수있다.
하지만, 아주 치명적인 문제가 발생한다. 아래의 그림과 같이 생성자로 생성한 모든 인스턴스에 똑같은 메서드가 추가된다. 생성한 인스턴스만큼 같은 작업을 하는 메서드가 추가된다 . 메모리가 크게 낭비 된다.
-> 이는 프로토타입이 지니는 "공유"라는 특징 때문이다. 프로토타입이라는 뜻은 원형이라는 뜻이다. 생성자로부터 만들어진 객체(var EQ90 = new Car('EQ90', 'sedan'))은 결국 원형객체인 Car을 공유한다. 그래서 이 Car의 프로토타입객체에 horn이라는 메소드를 넣으면 Car생성자로 만든 모든 객체는 이 메소드 사용이 가능하다. 공유하고 있기 때문이다.
특징 2. 프로토타입 객체
프로토타입 객체를 이용하면, 생성자 안에 있는 프로토타입 프로퍼티(CarType)가 외부에 정의된 객체(car1, car2, car3)를 가리킨다. 그리고 그 프로토타입 객체에 prototype키워드로 객체와 지정한 함수(printCarName)를 저장하는 것이다.
결국, 인스턴스에서도 그 함수를 가리키게 되는 것이다. 객체가 아무리 많아진다 해도, 함수는 1개만 존재할 뿐이다.
(인스턴스의 __ proto __도 생성자 함수의 prototype객체의 printCarName을 가리킨다.) 함수가 생성되면서, 함수는 생성자 자격을 얻게되고, prototype Object를 생성한다. 함수의 prototype프로퍼티를 통해서 prototype Object를 가리킨다.
-
즉, 함수를 정의하면 생성자 자격을 부여하고 해당 함수의 prototype Object을 생성, 연결한다.
-
constructor자격이 부여되어야 new 키워드를 통해 객체(인스턴스)를 만들 수 있다.
-
__ proto __는 prototype과 다르다. 전자는 모든 객체가 가지고 있지만, 후자는 함수만 가지고 있는 프로퍼티이다.
-
함수도 객체이기 때문에, __ proto __를 가지고 있다.
-> car2인스턴스에서 __ proto __를 이용해서 printCarName을려고 했는데 printCarName이 없다면 CarType의 프로토타입 객체의 상위 객체의 속성을 찾는다. 최상위 객체인 Object까지 검색한다. 찾지 못한다면, undefined를 리턴한다. Object prototype 객체의 constructor은 Object 생성자 함수이고, __ proto __는 null이다. 그 상위의 객체가 없기 때문이다.( 모든 객체는 Object생성자 함수로 부터 생성된다.)
- constructor는 생성자 함수 그 자체를 가리킨다. 즉 자신을 생성한 객체를 가리킨다.
- prototype은 생성자 함수에 정의한 모든 객체가 공유할 원형
- _proto_는 생성자 함수를 new로 호출할 때, 정의해두었던 prototype을 참조한 객체
- prototype은 생성자 함수에 사용자가 직접 넣는 거고, _proto_는 new를 호출할 때 prototype을 참조하여 자동으로 만들어진다.
- 생성자에는 prototype, 생성자로부터 만들어진 객체에는 _proto_
- 따라서 사용자는 prototype만 신경쓰면 된다. _proto_는 prototype이 제대로 구현되었는지 확인용으로 사용한다.
이제 조금더 확실하게 이해가 간것같다. 위의 글들이 이해가 잘안간다면, prototype이 개발자입장에서 객체에 변화를 주기위해 access해야 될 것이고, _proto_는 생성자로부터 만들어진 객체가 prototype을 참조한 객체이다.
특징 3. 상속
프로토타입을 이용해서 상속 구조를 만들 수 있다. 객체 원형의 위임 과정을 통해 상속 과정이 구현된다. 그러나 클래스 기반 상속과 다르다. 클래스 기반 상속을 비슷하게 흉내내는 것이다.
-
__ proto __를 이용해서 프로퍼티를 찾아다닌다.
-
contructor는 해당 프로토타입의 생성자 함수를 가리킨다.
-
생성자 함수의 prototype 프로퍼티는 constructor을 가리킨다.
-> (다만 자바스크립트는 오직 하나의 클래스를 상속받는 것만 지원한다.) 이 특별한 클래스는 흔히 자식 클래스(child)라고 불리우고 원본 클래스는 흔히 부모 클래스(parent)라고 불리운다. 자바스크립트에서는 부모 클래스의 인스턴스를 자식 클래스에 할당함으로써 상속이 이루어진다.
실제로 JS도 Class를 사용할 수 있게 되면서, 위와 같은 생성자 함수 형태는 거의 사용하고 있지 않다. 하지만, JS의 객체지향이 가지는 특징이므로 한 번 정리한 다음에 JS의 Class와 class 기반 언어의 객체지향 class 사용의 차이점을 본다면 좀 더 이해가 잘 될거라 생각한다.
Reference
'Programming Language > JS&TS' 카테고리의 다른 글
JavaScript_동기&비동기(이벤트 루프) (2) | 2021.02.11 |
---|---|
Javascript와 Node의 차이점을 정리해보자 (1) | 2021.01.21 |
JS 변수 선언 방식_ let, var, const의 차이 (0) | 2021.01.21 |
Typescript 이해하기 (0) | 2020.11.23 |
Ecma Script6문법 (0) | 2020.11.05 |