TIL)16 JS 자바스크립트 기초 이론 prototype 프로토타입 1

이명진·2021년 3월 9일
0
post-thumbnail

들어가기에 앞서..

오늘은 prototype에 대해서 배웁니다. 이론을 공부할때 이해가 안되서 두번 읽어봤지만 그래도 어려웠던 프로토타입..
정리하면서 다시 술술 읽어보며 세번 읽어봅니다
전반적인 내용은 모던자바스크립트를 보고 배운 내용입니다.

오늘은 무엇을 배울까 ?

프로토타입 체인 , constructor 프로퍼티 , [[Prototype]] vs prototype 프로퍼티 , 프로토타입 객체

프로토타입 객체

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

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

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

다음은 예이다.

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

student 객체는 proto 프로퍼티로 자신의 부모 객체(프로토타입 객체)인 Object.prototype을 가리키고 있다.
자바스크립트 모든 객체의 어머니는 object이다.

[[Prototype]] vs prototype 프로퍼티

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

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

prototype 프로퍼티와 [[Prototype]]은 모두 프로토타입 객체를 가리키지만 관점의 차이가 있다.

[[Prototype]]

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

prototype 프로퍼티

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

constructor 프로퍼티

프로토타입 객체는 constructor 프로퍼티를 갖는다. 이 constructor 프로퍼티는 객체의 입장에서 자신을 생성한 객체를 가리킨다

function Person(name) {
this.name = name;
}
var foo = new Person('Lee');
// Person() 생성자 함수에 의해 생성된 객체를 생성한 객체는 Person() 생성자 함수이다.
console.log(Person.prototype.constructor === Person);
// foo 객체를 생성한 객체는 Person() 생성자 함수이다.
console.log(foo.constructor === Person);
// Person() 생성자 함수를 생성한 객체는 Function() 생성자 함수이다.
console.log(Person.constructor === Function);

  1. Person() 생성자 함수에 의해 foo라는 객체가 생성되었다.
  2. Person()은 생성자 함수이다
  3. foo 객체 입장에서 자신을 생성한 객체는 Person() 생성자 함수이며, foo 객체의 프로토타입 객체는 Person.prototype이다.
  4. 따라서 프로토타입 객체 Person.prototype의 constructor 프로퍼티는 Person() 생성자 함수를 가리킨다.

Prototype chain

자바스크립트는 특정 객체의 프로퍼티나 메소드에 접근하려고 할 때 해당 객체에 접근하려는 프로퍼티 또는 메소드가 없다면 [[Prototype]]이 가리키는 링크를 따라 자신의 부모 역할을 하는 프로토타입 객체의 프로퍼티나 메소드를 차례대로 검색한다

객체 생성 방법은 3가지가 있다.

  • 객체 리터럴
  • 생성자 함수
  • Object() 생성자 함수

객체리터럴 객체의 프로토타입 체인

객체 리터럴 방식으로 생성된 객체는 결국 내장 함수(Built-in)인 Object() 생성자 함수로 객체를 생성하는 것을 단순화시킨 것이다. 자바스크립트 엔진은 객체 리터럴로 객체를 생성하는 코드를 만나면 내부적으로 Object() 생성자 함수를 사용하여 객체를 생성한다.
Object() 생성자 함수는 일반 객체와 달리 prototype 프로퍼티가 있다.

  • prototype 프로퍼티는 함수 객체가 생성자로 사용될 때 이 함수를 통해 생성된 객체의 부모 역할을 하는 객체, 즉 프로토타입 객체를 가리킨다.(?)
  • [[Prototype]]은 객체의 입장에서 자신의 부모 역할을 하는 객체, 즉 프로토타입 객체를 가리킨다.(?)

모던 자바스크립트는 애매하게 둘다 프로토 타입 객체를 가리킨다고 나왔다. 여기서 이해가 안되는데 결국 둘은 부모를 가리킨다 라고 생각했다.

아래 예시를 보자.

var person = {
name: 'Lee',
gender: 'male',
sayHello: function(){
  console.log('Hi! my name is ' + this.name);
}
};

console.dir(person);

console.log(person.__proto__ === Object.prototype);   // ① true
console.log(Object.prototype.constructor === Object); // ② true
console.log(Object.__proto__ === Function.prototype); // ③ true
console.log(Function.prototype.__proto__ === Object.prototype); // ④ true

결론적으로 객체 리터럴을 사용하여 객체를 생성한 경우, 그 객체의 프로토타입 객체는 Object.prototype이다.

생성자 함수로 생성된 객체의 프로토타입 체인

함수를 정의하는 방식은 3가지가 있다.

  • 함수선언식(Function declaration)
  • 함수표현식(Function expression)
  • Function() 생성자 함수

함수선언식, 함수표현식 모두 함수 리터럴 방식을 사용한다. 함수 리터럴 방식은 Function() 생성자 함수로 함수를 생성하는 것을 단순화 시킨 것이다
즉, 3가지 함수 정의 방식은 결국 Function() 생성자 함수를 통해 함수 객체를 생성한다, 따라서 어떠한 방식으로 함수 객체를 생성하여도 모든 함수 객체의 prototype 객체는 Function.prototype이다

다시한번 봐도 역시나 어려운 이론이다. 나머지 이론이 더 있으나 내용이 길어짐을 방지하기 위해서 다음 포스팅으로 이어서 작성하도록 하겠다.

profile
프론트엔드 개발자 초보에서 고수까지!

0개의 댓글