하루 30분 모던 자바스크립트 딥 다이브 프로토타입1

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

객체지향 프로그래밍

  1. 명령형 프로그래밍의 절차지향적 관점에서 벗어난, 여러 개의 독립적 단위, 즉 객체의 집합으로 프로그래밍을 표현하려는 패러다임
  2. 다양한 속성 중에서 필요한 속성을 간추려 내는 것을 추상화라 한다
  3. 속성을 통해 여러 개의 값을 하나의 단위로 구성한 복합 자료구조를 객체라고 한다
  4. 상태를 나타내는 데이터는 프로퍼티, 동작은 매서드

상속과 프로토타입

  1. 어떤 객체의 프로퍼티, 메서드를 다른 객체가 상속받아 그대로 사용할 수 있는 것
  2. 상속을 구현하여 불필요한 중복을 제거한다.
function Circle(radius){
	this.radius = radius;
	this.getDiameter = function () {
		return this.radius*2;
	}
}
const circle1 = new Cicle(5);
const circle2 = new Circle(10)
  1. 위와 같이 코드를 작성한다면, getDiameter 메서드를 중복 생성하고 인스턴스가 중복 소유한다
function Circle(radius){
	this.radius = radius;
}
Cicle.prototype.getDiameter = function () {
		return this.radius*2;
}
const circle1 = new Cicle(5);
const circle2 = new Circle(10)
  1. 위 코드는 프로토타입을 기반으로 상속을 구현하였다. 부모 객체인 프로토타입의 자산을 공유하였다.

프로토타입 객체

  1. 모든 객체는 [[Prototype]]이라는 내부 슬롯을 가진다. 이에 저장되는 프로토타입은 객체 생성 방식에 의해 결정된다.
  2. 예를 들어, 객체 리터럴에 의해 생성된 객체의 프로토타입은 Object.prototype이고, 생성자 함수로 생성된 프로토타입은 생성자 함수의 prototype 프로퍼티에 바인딩되어 있는 객체이다.

proto 접근자 프로퍼티

  1. [[Prototype]] 내부 슬롯은 __proto__를 통해 간접 접근 가능
  2. 내부 슬롯은 프로퍼티가 아니다.
  3. getter/setter함수를 통해 프로토타입을 취득하거나 할당한다.
  4. 상속을 위해 사용된다. 모든 객체는 상속을 통해 접근자 프로퍼티를 사용할 수 있다.
  5. 접근자 프로퍼티를 사용하는 이유는 상호 참조에 의해 프로토타입 체인이 생성되는 것을 방지하기 위해서다.
    1. 프로토타입 체인은 단방향 링크드 리스트로 구현되어야 한다.
    2. 슌환 참조가 만들어지면 프로토타입 체인 종점이 존재하지 않게 되며 무한 루프에 빠진다.
  6. 접근자 프로퍼티를 코드 내에서 직접 사용하는 것은 권장하지 않는다.
    1. Object.getPrototypeOf 메서드를 통해 취득
    2. Object.setPrototypeOf메서드를 통해 교체

함수 객체의 prototype 프로퍼티

  1. 함수 객체만 소유하는 prototype 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킨다.
  2. non-constructor인 화살표 함수와 ES6 메서드 축약 표현으로 정의한 메서드는 prototype 프로퍼티를 소유하지 않는다.
  3. proto 접근자 프로퍼티 와 함수 객체의 prototype 프로퍼티는 결국 동일한 프로토타입을 가리킨다.

프로토타입의 Constructor 프로퍼티와 생성자 함수

  1. 모든 프로토타입은 Constructor 프로퍼티를 갖는다. prototype 프로퍼티로 자신을 참조하고 있는 생성자 함수를 가리킨다.

리터럴 표기법에 의해 생성된 객체의 생성자 함수와 프로토타입

  1. 리터럴 표기법에 의해 생성된 객체도 프로토타입이 존재한다.
  2. 하지만 constructor 프로퍼티가 가리키는 생성자 함수가 반드시 객체를 생성한 함수라고 단정할 수는 없다.
  3. Object 생성자 함수 호출과 객체 리터럴의 평가는 추상 연산 OrdinaryObjectCreate를 호출하여 빈 객체를 생성하는 점은 동일하나, new.target이나 프로퍼티를 추가하는 처리 등 세부 내용이 다르다.
  4. 함수 객체의 경우 생성자 함수를 호출하여 생성한 함수는 렉시컬 스코프를 만들지 않고, 전역 함수인 것처럼 스코프를 생성하며 클로저도 만들지 않는다.
  5. 따라서 함수 선언문과 함수 표현식을 평가하여 함수 객체를 생성한 것은 Function 생성자 함수가 아니지만, constructor 프로퍼티를 통해 확인하면 생성자 함수는 Function 생성자 함수이다.
  6. 리터럴 표기법에 의해 생성된 객체도 가상적인 생성자 함수를 갖는다.
  7. 프로토타입과 생성자 함수는 단독으로 존재할 수 없고 언제나 쌍으로 존재.
  8. 결국 프로토타입의 constructor 프로퍼티를 통해 연결되어 있는 생성자 함수를 리터럴 표기법으로 생성한 객체를 생성한 생성자 함수로 생각해도 무리가 없다.리터럴 표기법 생성자 함수 프로토타입
    객체 Object Object.prototype
    함수 Function Function.prototype
    배열 Array Array.prototype
    정규 표현식 RegExp RegExp.prototype