EnJinnier

JS Deep Dive - 19. 프로토타입 본문

스터디/모던 자바스크립트 Deep Dive

JS Deep Dive - 19. 프로토타입

공학도진니 2024. 5. 10. 05:21

자바스크립트는 객체 기반의 프로그래밍 언어이며 원시 타입의 값을 제외한 나머지 값들(함수, 배열, 정규 표현식 등)은 모두 객체다.

19.1 객체지향 프로그래밍

: 여러개의 독립적 단위, 즉 객체(속성을 통해 여러개의 값을 하나의 단위로 구성한 복합적인 자료구조)

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

추상화abstraction : 다양한 속성 중에서 프로그램에 필요한 속성만 간추려내어 표현하는 것. 

이때 객체의 상태 데이터를 프로퍼티, 동작을 메서드라고 부름.

 

19.2 상속과 프로토타입

상속 : 어떤 객체의 프로퍼티 또는 메서드를 다른 객체가 상속받아 그대로 사용할 수 있는 것.

자바스크립트는 프로토타입을 기반으로 상속을 구현하여 불필요한 중복을 제거한다.

 

예를들어, 생성자 함수를 만들때 동일한 메소드를 기술하게 되면 객체를 생성할때마다 메소드를 생성하게 된다.

따라서 프로토타입을 기반으로 상속을 구현해 불필요한 중복을 제거하는 것이 좋다.

Circle 생성자 함수가 생성한 모든 인스턴스는 자신의 프로토 타입, 즉 상위(부모)객체 역할을 하는 Circle.prototype의 모든 프로퍼티와메서드를 상속받는다.

 

프로토타입에 추가하면 중복 생성하지않고 공유해서 사용할 수 있다.

 

19.3 프로토타입 객체

프로토타입은 어떤 객체의 상위(부모)객체의 역할을 하는 객체로서 다른 객체에 공유 프로퍼티(메서드 포함)를 제공한다.

모든 객체는 [[Prototype]]이라는 내부 슬롯을 가지며

객체가 생성될 때 객체 생성방식에 따라 프로토타입이 결정되고 〔[Prototype]]에 저장된다.

 

모든 객체는 하나의 프로토타입을 갖고, 모든 프로토타입은 생성자 함수와 연결되어 있다.

[[Prototype]]내부슬롯에는 직접 접근할 수 없지만, __proto__접근자 프로퍼티를 통해 자신의 프로토타입, 즉 자신의 [[Prototype]] 내부 슬롯이 가리키는 프로토타입에 간접적으로 접근할 수 있다.

프로토타입은 자신의 constructor 프로퍼티를 통해 생성자 함수에 접근할 수 있고, 생성자 함수는 자신의 prototype 프로퍼티를 통해 프로토타입에 접근할수 있다.

 

__proto__ 접근자 프로퍼티

모든 객체는 __proto__ 접근자 프로퍼티를 통해 자신의 프로토타입, 즉 [[Prototype]] 내부슬롯에 간접적으로 접근할 수 있다.

(접근자 프로퍼티: 자체적으로는 값([[Value]] 프로퍼티 어트리뷰트)을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용하는 접근자 함수, 즉 [[Get]], [[Set]] 프로퍼티 어트리뷰트로 구성된 프로퍼티)

get

 

set

하지만 모든 객체가 __proto__ 접근자 프로퍼티를 사용할 수 있는 것은 아니기 때문에 코드 내에서 __proto__ 접근자 프로퍼티를 직접 사용하는 것은 권장하지 않는다. 대신 프로토타입의 참조를 취득하고 싶은 경우에는 Object.getPrototypeOf 메서드를 사용하고, 프로토타입을 교체하고 싶은 경우에는 0bject.setPrototypeOf 메서드를 사용할 것을 권장한다.

__proto__와 prototype 프로퍼티의 차이점

constructor 프로퍼티

constructor 프로퍼티는 prototype 프로퍼티로 자신을 참조하고 있는 생성자 함수를 가리킨다.

생성자 함수에 의해 생성된 인스턴스는 프로토타입의 constructor 프로퍼티에 의해 생성자 함수와 연결된다.

따라서 constructor 프로퍼티가 가리키는 생성자 함수는 인스턴스를 생성한 생성자 함수다.

이때 리터럴 표기법에 의한 객체 생성 방식과 같이 명시적으로 new 연산자와 함께 생성자 함수를 호출하지 않는 경우 constructor 프로퍼티가 가리키는 생성자 함수가 반드시 객체를 생성한 생성자 함수라고 단정할 수는 없다.

 

19.7 프로토타입 체인

위와 같은 예제가 있을때 me 객체의 프로토타입은 Person.prototype이고 Person.prototype의 프로토타입은 Object.prototype이다. (프로토타입의 프로토타입은 언제나 Object. prototype)

따라서 위 예제를 그림으로 표현하면 다음과 같다.

자바스크립트는 객체의 프로퍼티(메서드 포함)에 접근하려고 할 때 해당 객체에 접근하려는 프로퍼티가 없다면[[Prototype]] 내부슬롯의참조를 따라 자신의 부모 역할을 하는 프로토타입의 프로퍼티를 순차적으로 검색한다. =프로토타입 체인

프로토타입 체인은 자바스크립트가 객체지향 프로그래밍의 상속을 구현하는 메커니즘이다.

 

프로토타입 쳬인의 최상위에 위치하는 객체는 언제나 Object.prototype이므로 Object.prototype을 프로토타입 체인의 종점(end of prototype chain)이라 한다. Object.prototype의프로토타입, 즉 [[Prototype]] 내부슬롯의 값은 null이다.

(Object.prototype에서도 프로퍼티를 검색할 수 없는 경우 undefined를 반환)

 

프로퍼티가 아닌 식별자는 스코프 체인에서 검색한다. 따라서 스코프 체인은 식별자 검색을 위한 메커니즘이라고 할 수 있다.

 

19.11 직접 상속

Object.create에 의한 직접 상속

0bject.create 에서드의 첫 번째 매개변수에는 생성할 객쳬의 프로토타입으로 지정할 객체를 전달한다.

두 번째 매개변수에는 생성할 객체의 프로퍼티 키와 프로퍼티 디스크립터 객체로 이뤄진 객체를 전달한다.(생략가능)

이처럼 Object.create 메서드는 첫 번째 매개변수에 전달한 객쳬의 프로토타입 체인에 속하는 객체를 생성한다. 즉, 객체를 생성하면서 직접적으로 상속을 구현하는 것이다. 

장점 : new연산자가 없이도 객체를 생성할 수 있음. 

프로토타입을 지정하면서 객체를 생성할 수 있음.

객체 리터럴에 의해 생성된 객체도 상속받을 수 있음.

객체 리터럴 내부에서 __proto__에 의한 직접 상속

 19.12 정적 프로퍼티/메서드

정적static프로퍼티/메서드: 생성자 함수로 인스턴스를 생성하지 않아도 참조/호출할 수 있는 프로퍼티/메서

19.13 프로퍼티 존재 확인

in 연산자

객체 내에 특정 프로퍼티가 존재하는지 여부를 확인

(has 메서드도 in 메서드와 동일하게 동작함)

Object.prototype.hasOwnProperty 메서드