프로토타입과 클래스

수툴리 양·2021년 6월 15일
0
post-thumbnail

참고
[Code States]
[코어 자바스크립트 by 정재남 | 위키북스]

클래스와 프로토타입 이 둘은 자바스크립트의 객체지향 성격과 관련되어 있다.

⚀ 객체지향 프로그래밍

객체지향이란 하나의 모델(class)이 되는 청사진을 만들고 그것을 바탕으로 한 객체(instance object)를 만드는 프로그래밍 패턴. 일종의 패러다임.
절차적 프로그래밍이 불편함을 느껴, 보다 실제 기능과 코드가 닮아있는 즉 실생활 모습, 사람의 생각과 유사한 객체지향 프로그래밍으로 전향.

❓ 자바스크립트는 객체지향 언어인가요
No. 하지만 객체지향 패턴으로 프로그래밍할 수 있다. 언어가 탄생된 방식은 객체지향이 아니다. ES6에서 도입.
자바스크립트는 프로토타입 기반 언어이다.
클래스 기반 언어는 상속 inheritance를 사용하나 프로토타입 기반에서는 원형 객체를 참조함으로써 비슷한 효과를 지닌다. 이를 프로토타입 체이닝을 통해 확인할 수 있다.
(참고) 리액트에서도 변할 수 있는 값인 this의 사용을 줄이고자 함수형 컴포넌트로 전환


⚁ 클래스

생성자 함수 Constructor

클래스는 모팔모가 칼을 찍어내는 거푸집(틀)이다. die 또는 mold이다.
생성자함수는 칼의 브랜드나 이름, 색상 등을 부여하는 parameter를 정의하는 것이다.

// 클래스 생성
class Student {
  constructor(name, age, enrolled, score) { // 생성자 함수로 속성 멤버 정의
    this.name = name; // this는 이 클래스 틀을 가지고 만들 인스턴스객체를 가리킴
    this.age = age;
    this.enrolled = enrolled;
    this.score = score;
  }
}
// new 연산자를 사용해 만든 인스턴스 객체를 요소로 갖는 배열
const students = [ 
  new Student('A', 29, true, 45), 
  new Student('B', 28, false, 80),
  new Student('C', 30, true, 90),
  new Student('D', 40, false, 66),
  new Student('E', 18, true, 88),
];

이렇게 생성자함수와 new 연산자를 사용해 생성한 각각의 인스턴스는 클래스의 고유한 속성과 메소드를 지니게 된다.
[(참고) MDN 공식문서의 클래스 상속 실습 예제]
(출처: 코어 자바스크립트 | CodeStates(재구성))


class Human {
  constructor(name, age) {
  	// 속성
    this.name = name;
    this.age = age;
  }
// 메소드
  eat() { // 생략 // };
  sleep() { // 생략 //};
  :
  :
}

let human = new Human('Jay', 22);

Human.prototype.constructor === Human; // true
Human.prototype === human.__proto__; // true
Human.prototype.sleep === human.sleep; // true

❗️ constructor가 자기자신을 참조하므로, 인스턴스객체의 원형객체를 찾을 수 있음을 위와 같이 확인할 수 있다.
❗️ 인스턴스 human의 .__proto__(속성, *객체임)를 통해 Human.prototype(객체)에 접근이(참조) 가능하다.

Human.prototype.constructor === human.__proto__.constructor
// 이것은 같은 주소를 가리킨다.

❗️ .__proto__는 생략 가능하다. 따라서 인스턴스도 원형객체의 메소드를 마치 자신의 것처럼 쓸 수 있는 것이다.
이렇게 인스턴스에서는 __proto__속성을 거슬러 올라가보면 원형객체(클래스.prototype)에 도달한다.

✮ 프로토타입 기반 언어인 자바스크립트에서 클래스 상속을 잘 구현했다는 건 프로토타입 체이닝을 잘 연결한 것을 의미한다. (이에 대한 샘플을 다음 프로토타입 문단의 콘솔창 스크린샷에서 확인해보자.)


  • 속성은 속성끼리, 기능(메소드)은 기능끼리 모아서 실제 모습과 비슷하게 코드를 작성하는 것, 이것부터 캡슐화 encapsulation 라고 할 수 있다.
  • 클래스 내부에서 속성과 기능을 모아두었으니 이 class의 속성들은 해당 class 내부의 메소드로만 변경 가능하게 하는 것이 은닉화 hiding이다.
  • 클래스 내부에서 정의한 메소드 등의 인터페이스, 이것이 추상화이다.
    클래스 내부를 완벽히 만들면 그 이후엔 우리는 내부 구현에 더 이상 신경 쓰지 않고 보다 비즈니스 로직에 집중하면 되는 것이다.


⚂ 프로토타입

자바스크립트는 객체, 함수에(함수도 객체이다.) 자동으로 "prototype객체" 프로퍼티를 생성해놓는다.

MDN에 따르면 이렇게 정의되어 있다.

  • prototype(객체)의 속성은 상속시키려는 멤버(속성property, 메소드)들이 정의된 객체를 가리킨다.
    prototype a property containing an object on which you define memebers that you want to be inherited.
  • prototype객체는 (.__proto__)속성으로 접근 가능한 내장 객체이다.


객체나 배열의 생성자함수constructor 속성을 찾기 위해 살펴보면, __proto__ 속성 안에서(하위) 찾을 수 있다.
constructor(생성자함수)의 프로퍼티인 prototype객체 내부에 'constructor' 프로퍼티가 또 있다.
__proto__ 속성 안에는 또 __proto__ 속성이 있다.
→ 여기서 우리는 클래스의 프로토타입, 원형 객체인 constructor 생성자함수가 자기 자신을 참조하는 것을 다시 한번 확인할 수 있고,
따라서 클래스의 프로퍼티를 상속받은 실존 개체인 인스턴스에서 원형객체를 어떻게든 찾아갈 수 있는 것이다. ↩︎

[MDN 공식문서의 프로토타입 상속 실습 예제]



위 내용들의 근본은
" 기본적으로 모든 . __proto__ 를 쫓아 올라가면 Object.prototype이 연결되어 있다" 는 것이다.
임의의 배열 또한, Array의 prototype객체가 Object이기 때문이고, "prototype객체" 또한 '객체'이므로 그러하다.
이를 그림으로 표현하면 아래와 같다.
(출처: 코어 자바스크립트)

💪 advanced issues

✘ constructor로 생성자 정보를 알아내기가 안전하지는 않음
✘ 어떤 클래스의 속성을 부여받은 인스턴스는 클래스프로토타입의 속성에 접근 가능 및 메소드 호출이 가능하지만, 클래스의 static 프로퍼티와 메소드에는 접근 불가
→ Array의 경우 static property로 length, static method로 isArray() 등.
* .filter(), .map() 등의 메소드들은 prototype(객체) 내부의 속성이라 인스턴스가 호출 가능하다.
✘ 클래스 자체에 구체적인 데이터값을 지니지 않게 하는 방법
✘ 자바스크립트 엔진은 데이터 자신의 프로퍼티를 검색해서 원하는 메소드를 찾으면 해당 메소드를 실행하고, 없으면 .__proto__를 검색해서 실행하고, 없으면 다시 .__proto__를 검색하고 (...)
→ 이것은 메서드 오버라이드와 관련되어 있다.
현재 위치(객체)에서 접근 가능한 가장 가까운 메서드가 덮어씌워진다. ↩︎


🆘 리액트 과제에서의 source.soucre.src 사태를 프로토타입과 클래스에 대한 개념 정리로 정리할 수 있었다. R.I.P. ✞

profile
developer; not kim but Young

0개의 댓글