[JS] 프로토타입이란?

hahaha·2021년 8월 8일
0

JavaScript

목록 보기
7/24
post-thumbnail

들어가기 전에

자바 스크립트

  • 명령형, 함수형, 프로토타입 기반, 객체지향 프로그래밍을 지원하는 멀티 패러다임 프로그래밍 언어이다.
  • JS를 이루고 있는 거의 "모든 것"이 객체 이다. (원시 타입의 값을 제외한)

객체지향 프로그래밍

: 객체의 집합으로 프로그램을 표현하려는 프로그래밍 패러다임

  • 상태 데이터(프로퍼티)와 동작(메서드)을 하나의 논리적인 단위로 묶은 복합적인 자료구조

상속과 프로토타입

  • 프로토타입을 기반으로 상속을 구현 -> 코드 재사용 -> 불필요한 중복 제거
function Circle(radius) {
  this.radius = radius;
  //this.getArea = function () { ... }
  // -> 인스턴스를 생성할 때 마다 동일한 메서드가 중복 생성됨
}

// 프로토타입 기반 상속을 구현 -> 불필요한 중복 제거
Circle.prototype.getArea = function () {
  return Math.PI * this.radius ** 2;
};

// 인스턴스 생성
const circle1 = new Circle(1);
const circle2 = new Circle(2);

console.log(circle1.getArea === circle2.getArea); // true
// -> Circle 생성자 함수가 생성하는 모든 인스턴스는 하나의 getArea 메서드를 공유

프로토타입 객체(프로토타입)

  • 어떤 객체의 상위(부모) 객체의 역할을 하는 객체
  • 다른 객체에 공유 프로퍼티(메서드 포함)를 제공
  • 모든 객체는 하나의 프로토타입을 가짐
    -> [[Prototype]] 이라는 내부 슬롯을 지님
  • 생성자 함수가 생성되는 시점에 생성됨

1. __proto__ 프로퍼티

  • [[Prototype]]내부 슬롯에 직접 접근 불가
  • __proto__ 접근자 프로퍼티를 통해 객체 자신의 프로토타입에 간접 접근 가능
  • 프로토타입은 자신의 constructor 프로퍼티를 통해 생성자 함수에 접근
  • 접근자 프로퍼티이므로 자체적으로 값을 가지진 않는다.
  • 상속을 통해 사용
    -> 객체가 직접 소유하는 프로퍼티가 아닌, Object.prototype의 프로퍼티
  • 코드 내에서 직접 사용하는 것 권장하지 않음
    -> getPrototypeOf, setPrototypeOf 메서드 이용

2. prototype 프로퍼티

  • 함수 객체만이 소유한다.
  • 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킨다.
  • 생성자 함수로서 호출할 수 없는 함수는 prototype 프로퍼티와 프로토타입을 생성 X
    ex. 화살표 함수, ES6의 메서드 축약 표현으로 정의한 메서드

3. 프로토타입의 constructor 프로퍼티와 생성자 함수

  • 모든 프로토타입은 constructor 프로퍼티를 가짐
  • 이 constructor 프로퍼티는 prototype 프로퍼티로 자신을 참조하고 있는 생성자 함수를 가리킴

프로토타입 체인

  • JS가 객체지향 프로프래밍의 상속을 구현하는 메커니즘
  • 객체의 프로퍼티(메서드 포함)에 접근하려 할 때,
    해당 객체에 접근하는 프로퍼티가 없다면
    [[Prototype]] 내부 슬롯의 참조를 따라 프로토타입의 프로퍼티를 순차적으로 검색
  • 프로토타입 체인의 최상위에 위치하는 객체는 언제나 Object.prototype
    -> 프로토타입 체인의 종점
    -> [[Prototype]] 내부 슬롯의 값 = null

오버라이팅과 프로퍼티 섀도잉

  • 프로토타입 프로퍼티: 프로토타입이 소유한 프로퍼티(메서드 포함)
  • 인스턴스 프로퍼티: 인스턴스가 소유한 프로퍼티
  • 프로토타입 프로퍼티와 같은 이름의 프로퍼티를 인스턴스에 추가하면,
    인스턴스 프로퍼티로 추가됨 => 오버라이딩
  • 프로토타입 프로퍼티는 인스턴스 프로퍼티에 의해 가려짐 -> 프로퍼티 섀도잉
  • 하위 객체를 통해 프로퍼티의 프로퍼티 변경 및 삭제 불가능

instanceof 연산자

  • 객체 instanceof 생성자 함수
  • 생성자 함수의 prototype에 바인딩된 객체가 좌변 객체의 프로토타입 체인 상에 존재하면 true 반환

프로퍼티 존재 확인

1. in 연산자

  • key in object
  • Reflect.has(object, key) (ES6)
  • 객체 내에 특정 프로퍼티가 존재하는지 확인
  • 확인 대상 객체의 프로퍼티 뿐만 아니라 상속받은 모든 프로토타입의 프로퍼티 확인

2. Object.prototype.hasOwnProperty 메서드

  • 상속받은 프로토타입의 프로퍼티 키 검사 X

프로퍼티 열거

1. for ... in 문

  • for(변수 선언문 in 객체) { ... }
  • 객체의 모든 프로퍼티를 순회하며 열거
  • 상속받은 프로토타입의 프로퍼티까지 열거
    - 프로퍼티 어트리뷰트 [[Enumerable]] 값이 true인 프로퍼티
  • 순서 보장 X
  • 배열도 객체이므로, for문, for ... of문, forEach메서드 사용 권장

2. Object.keys/values/entries 메서드

  • 객체 자신의 고유 프로퍼티만 열거

Object.keys

  • 프로퍼티 키를 배열로 반환

Object.values

  • 프로퍼티 값을 배열로 반환

Object.entries

  • 프로퍼티 키와 값의 쌍의 배열을 배열로 반환
    ex. [[키, 값], [키, 값], ... ]
profile
junior backend-developer 👶💻

0개의 댓글