Prototype Link & Prototype Object

soom·2021년 1월 20일
2
post-thumbnail

Prototype Object

자바스크립트의 모든 객체는 자신의 부모 역할을 담당하는 객체와 연결되어 있다. 그리고 이것은 마치 객체 지향의 상속 개념과 같이 부모 객체의 프로퍼티 또는 메소드를 상속받아 사용할 수 있게 한다. 이러한 부모 객체를 Prototype(프로토타입) 객체 또는 줄여서 Prototype(프로토타입)이라 한다.

실질적인 자바스크립트 사용 질문으로써, 여기서 나타내는 프로토타입은 자신을 통해 만들어질 객체의 원형을 뜻한다.
정확히는 용어로는 프로토타입보다는 프로토타입 프로퍼티(prototype property) 를 의미한다.
prototype 프로퍼티란 아래와 같이 실제 코드에서 볼 수 있는 것을 의미한다.

Prototype 객체는 생성자 함수에 의해 생성된 각각의 객체에 공유 프로퍼티를 제공하기 위해 사용한다.

example 1.1

var student = {
  name: 'Lee',
  score: 90
};

// student에는 hasOwnProperty 메소드가 없지만 아래 구문은 동작한다.
console.log(student.hasOwnProperty('name')); // true

ECMAScript spec에서는 자바스크립트의 모든 객체는 [[Prototype]]이라는 인터널 슬롯(internal slot)를 가진다. [[Prototype]]의 값은 null 또는 객체이며 상속을 구현하는데 사용된다. [[Prototype]] 객체의 데이터 프로퍼티는 get 액세스를 위해 상속되어 자식 객체의 프로퍼티처럼 사용할 수 있다. 하지만 set 액세스는 허용되지 않는다. 라고 되어있다.

[[Prototype]]의 값은 Prototype(프로토타입) 객체이며 __proto__ accessor property로 접근할 수 있다. __proto__ 프로퍼티에 접근하면 내부적으로 Object.getPrototypeOf가 호출되어 프로토타입 객체를 반환한다.

example 1.2

var student = {
  name: 'Lee',
  score: 90
}
console.log(student.__proto__ === Object.prototype); // true

student 객체는 __proto__ 프로퍼티로 자신의 부모 객체(프로토타입 객체)인 Object.prototype을 가리키고 있다.

프로토타입의 2 가지 용어는 다음과 같다.

  • Prototype Link([[Prototype]]) - 자신을 만들어낸 객체의 원형
  • Prototype Object(Prototype Property) - 자신을 통해 만들어질 객체의 원형

모든 객체는 자신의 프로토타입 객체를 가리키는 [[Prototype]] 인터널 슬롯(internal slot) 을 갖으며 상속을 위해 사용된다.

함수도 객체이므로 [[Prototype]] 인터널 슬롯을 갖는다. 그런데 함수 객체는 일반 객체와는 달리 prototype 프로퍼티도 소유하게 된다.

example 2.1

function Person(name) {
  this.name = name;
}

var foo = new Person('Lee');

console.dir(Person); // prototype 프로퍼티가 있다.
console.dir(foo);    // prototype 프로퍼티가 없다.

  • __proto__ - 자신을 만들어낸 객체의 원형과 연결된 속성이다.
  • constructor - 생성자로써, 자신을 만들어낸 객체와 연결된 속성이다.
  • prototype - 자신을 원형으로 만들어진 새로운 객체들과 연결된 속성이다.

Prototype Object: Prototype Property

console.log(Person.prototype === foo.__proto__); //true

함수 객체만 가지고 있는 프로퍼티이다.
함수 객체가 생성자로 사용될 때 이 함수를 통해 생성될 객체의 부모 역할을 하는 객체(프로토타입 객체)를 가리킨다.

객체는 언제나 함수(Function)로 생성된다.

function Person() {} // => 함수
var personObject = new Person(); // => 함수로 객체를 생성

personObject 객체는 Person이라는 함수로 생성된 객체다. 이렇듯 언제나 객체는 함수에서 시작된다. 일반적인 객체 생성도 예외는 아닙니다.

var obj = {};
var obj = new Object(); // 같은 코드

위 코드 Object가 자바스크립트에서 기본적으로 제공하는 함수다. Object와 마찬가지로 Function, Array도 모두 함수로 정의되어 있다.

함수의 정의

  1. 해당 함수에 Constructor(생성자) 자격 부여
    Constructor 자격이 부여되면 new를 통해 객체를 만들어 낼 수 있게 된다. 이것이 함수만 new 키워드를 사용할 수 있는 이유이다.

  1. 해당 함수의 Prototype Object 생성 및 연결
    함수를 정의하면 함수만 생성되는 것이 아니라 Prototype Object도 같이 생성이 됩니다.

그리고 생성된 함수는 prototype이라는 속성을 통해 Prototype Object에 접근할 수 있다. Prototype Object는 일반적인 객체와 같으며 기본적인 속성으로 constructor__proto__를 가지고 있다.


constructorPrototype Object와 같이 생성되었던 함수를 가리키고 있다.
__proto__Prototype Link이다.

console.log(Person.__proto__ === Function.prototype); //true

함수를 포함한 모든 객체가 가지고 있는 인터널 슬롯이다.
객체의 입장에서 자신의 부모 역할을 하는 프로토타입 객체를 가리키며 함수 객체의 경우 Function.prototype를 가리킨다.

kim에는 eyes라는 속성이 없는데도 kim.eyes를 실행하면 2라는 값을 참조하는 것을 볼 수 있다.

kim객체가 eyes를 직접 가지고 있지 않기 때문에 eyes 속성을 찾을 때 까지 상위 프로토타입을 탐색한다.
최상위인 ObjectPrototype Object까지 도달했는데도 못찾았을 경우 undefined를 리턴한다.

이렇게 __proto__속성을 통해 상위 프로토타입과 연결되어있는 형태를 프로토타입 체인(Chain)이라고 한다.

exmaple 2.2.1

var person = function () {
  this.hp = function () {
    console.log('100');
  };
};

person.hp = function () {
  console.log('50');
};

var p1 = new person();
p1.hp(); // ?100

우리가 원하는 결과는 50 이지만 결과는 100 이다.

이러한 이유는 Prototype Object 는 생성 당시의 정보를 복제하기 때문이다.

example 2.2.2

var person = function () {};

person.hp = function () {
  console.log('100');
};

person.prototype.hp = function () {
  console.log('50');
};

var p1 = new person();
p1.hp(); // 50

원하는 결과를 위한 예제는 다음과 같다.
이것이 가능한 이유는 p1의 원형이 되는 Prototype Object 에 직접 접근했기 때문이다.

Prototype Chain

exmaple 3.1

var person = function () {
  this.hp = function () {
    // 상속
    console.log('100');
  };
};

// 공유
person.prototype.power = 5;

var p1 = new person();
var p2 = new person();

p1.hp = function () {
  console.log('50');
};

p1.mp = function () {
  console.log('100');
};

p1.hp(); // 50
p2.hp(); // 100

p1.mp(); // 100
p2.mp(); // p2.mp is not a function

p1.power; // 5
p2.power; // 5

p1.toString(); // [object]

위처럼 연결이 이어진 관계를 프로토타입 체인(prototype chain) 이라고 한다. 연결은 __proto__ 프로퍼티를 통해 이어진다.
이것을 이용해 자바스크립트 내부에서는 하위에서 최상위(Object)까지 탐색한다.

Prototype vs Class

클래스(Class)란 Java, Python, Ruby등 객체지향언어에서 빠질 수 없는 개념.

중요한 점은 자바스크립트도 객체지향언어. 자바스크립트에는 클래스라는 개념이 없다. 대신 프로토타입(Prototype)이라는 것이 존재한다. 자바스크립트가 프로토타입 기반 언어라고 불리는 이유.

클래스가 없으니 기본적으로 상속기능도 없다. 그래서 보통 프로토타입을 기반으로 상속을 흉내내도록 구현해 사용한다.

참고로 최근의 ECMA6 표준에서는 Class 문법이 추가되었다. 하지만 문법이 추가되었다는 것이지, 자바스크립트가 클래스 기반으로 바뀌었다는 것은 아니다.

다음의 글을 참고하였습니다.

profile
yeeaasss rules!!!!

0개의 댓글