티스토리 뷰

안녕하세요. 좋아요요정입니다.

자바스크립트는 프로토타입 기반 객체지향 프로그래밍 언어입니다. 

다른 객체지향 언어들과는 다르게 클래스나 상속, 캡슐화를 위한 키워드를 제공하지 않고 자바스크립트는 프로토타입을 활용해 자바스크립트만의 객체지향 패러다임을 제공하고 있습니다.

자바스크립트의 클래스는 ES6가 되어서야 도입이 되었고, 다른 언어(Java, C++ 등)과는 조금 다르게 동작합니다. 자바스크립트의 클래스는 기존 상속을 구현하던 프로토타입을 조금 더 쉽게 사용해주는 하나의 함수, 도우미 역할이라고 볼 수 있습니다.

 

 

 


프로토타입 객체

프로토타입을 활용한 상속이란? 

10. 생성자 함수에서 생성자 함수를 통해 객체 인스턴스를 생성하고, 생성자 함수의 prototype에 메서드를 등록함으로써 해당 메서드를 객체 인스턴스들이 사용할 수 있도록 생성했었습니다.

function AddCat(code, name, age) {
    if(!new.target) {
        return new AddCat(code, name, age)
    }
	this.code = code;
	this.name = name;
	this.age = age;

  AddCat.prototype.upAge = function () {
    this.age +=1; 
  }
}

const cookie = AddCat("2020-0320", "cookie", 3);
const latte = AddCat("2020-0321", "latte", 3);

이를 가능하게 해주는게 프로토타입을 기반으로 상속을 구현하였기 때문입니다. 

상속 기능을 통해 매번 동일한 함수를 생성하지 않고, 생성자 함수에 등록되어있는 메서드를 이용할 수 있기 때문에 효율적인 프로그래밍이 가능합니다.

 

 

 

프로토타입이란? 

프로토타입이란 객체간의 상속, 부모 역할을 하는 객체가 갖고있는 프로퍼티들을 자식 객체들이 활용할 수 있게 해주는 기능을 구현하기 위해 사용됩니다. 프로토타입의 사전적 의미는 원래의 형태 또는 전형적인 예, 기초 또는 표준이라고 되어 있습니다. 자바스크립트의 프로토타입도 이와 같은 의미를 가지고 있습니다. 

자바스크립트의 모든 객체는 [[Prototype]]이라는 내부 슬롯을 가지고 있습니다. 함수도 객체이므로 이 [[Prototype]] 내부 슬롯을 가지고 있습니다. 이 슬롯은 자바스크립트 엔진 내부에 구현된 로직이므로 개발자가 사용할 수 없지만, 프로토타입 내부 슬롯은 __proto__를 통해 간접적으로 접근할 수 있습니다.(권장되지 않습니다.) 

[[Prototype]] 내부 슬롯은 자기 자신의 프로토타입이 되는 객체를 가리킵니다. 프로토타입이 되는 객체도 자신의 프로토타입이 되는 객체를 가리키고, 이 동작의 끝은 프로토타입으로 null을 가지는 Object 객체에서 끝이 나게 됩니다.

이 [[Prototype]] 내부 슬롯을 통해 자바스크립트의 모든 객체는 자신의 원형이 되는 프로토타입의 객체와 연결이 되어 있습니다.

 

 

 

 

프로토타입은 어떻게 작용하게 되는 것일까요?

AddCat 생성자함수와 AddCat 생성자함수로 만들어진  Cookie를 살펴보면 다른 점이 있습니다.

Cookie는 데이터프로퍼티와 메서드, [[prototype]] 내부슬롯을 확인할 수 있고 AddCat 생성자함수에는 생성자함수의 메서드들과 prototype이라는 객체를 확인할 수 있습니다.

 

 

자바스크립트에서 생성자 함수를 생성하게 되면 생성자함수의 prototype도 함께 생성됩니다.

생성자함수에게는 prototype이라는 프로퍼티가 생성되고 prototype객체를 가리키고 있습니다.

생성자함수의 prototype에는 constructor에 자신을 가리키는 생성자함수를 저장하고, 생성자함수를 생성한 원형이 되는 객체를 저장하고 있습니다.

 

 

아까의 이미지를 다시 생각해보면, Object와 AddCat 생성자함수에게는 각각의 prototype 객체가 존재하고, prototype과 constructor로 서로를 가리키고 있습니다. 

객체 인스턴스의 prototype은 생성자함수 자체를 가리키는 것이 아니라 생성자함수의 prototype을 가르키게 됩니다.

그리고 prototype의 constructor로 연결되어있는 생성자함수와도 연결이 되어있으며, prototype의 내부슬롯 [[prototype]]을 통해 상위 생성자함수의 prototype도 계속해서 접근이 가능합니다.

 

 

 

 

 


cookie.prototype.upAge()로 작성하지 않아도 실행되는 이유

이전 스코프체인 기억나시나요? 

스코프체인에서 스코프 내부에 등록되어있는 식별자를 조회하고 변수가 선언되어있지 않으면 상위 스코프로 이동해서 변수를 찾았습니다. 

이와 비슷하게 객체에는 프로토타입 체인이 형성되어 있습니다.

객체에서 프로퍼티 사용하기 위해 조회할 때 prototype을 입력하지 않아도 객체에 등록되어있는 프로퍼티와 프로토타입체인에 연결되어있는 상위 객체의 프로퍼티까지 계속해서 조회가 가능합니다. 이를 통해 "상속"이 가능하게 됩니다. 

 

 

 

프로토타입은 모든 객체에 있을까요?

내부슬롯 [[Prototype]]은 모든 객체가 가지고 있습니다. 이를 통해 프로토타입 체인이 연결되죠.

prototype 객체는 함수 객체만 갖고 있는 프로퍼티입니다. 그러나 non-constructor인 메서드의 축약표현으로 생성된 함수나 화살표 함수()=>{} 로 정의된 함수는 prototype 프로퍼티가 존재하지 않습니다. 

 prototype 객체는 constructor 함수만 가지고 있는 프로퍼티입니다.

 

 

 

 

생성자함수가 없이 생성된 {}객체 리터럴은 상속받는게 불가능할까요? 

자바스크립트는 객체를 생성하는 방법이 현재 객체 리터럴, new Object(), 생성자 함수, 사용자정의 생성자 함수,  클래스, Object.create 메서드 5가지가 있습니다. 

 

각 생성 방식에는 차이가 있으나 자바스크립트 엔진은 객체를 생성할 때 추상연산에 의해 생성된다는 공통점이 있습니다.

추상연산(OrdinaryObjectCreate)는 자신이 생성할 객체를 인수로 받고 전달받은 값이 있으면 그 데이터의 prototype 객체, 없으면 {} 빈 객체를 할당하고 Object.prototype을 프로토타입으로 등록합니다.

이 추상연산을 통해 객체 리터럴도 Object의 기능을 상속받을 수 있습니다.

 

 

 

 

new Object() 생성자 함수

Object의 생성자는 주어진 값을 객체 래퍼로 만들어줍니다.

지난 12. 객체지향 프로그래밍에서 원시값이 메서드를 사용할 수 있는 이유는 프로퍼티에 접근할 때 원시 래퍼 객체가 생성되고, 프로퍼티를 사용 후에는 원시 래퍼 객체가 소멸되기 때문이라고 알게되었습니다.

Object 생성자 함수는 값이 없으면 빈 객체를 생성하고 반환, 주어진 값이 있으면 해당 타입의 객체를 반환합니다. 이 객체가 반환될 때 추상연산에 의해 prototype도 함께 등록되어 반환됩니다.

 

const num = new Object(2);

const string = new Object("좋아요요정");

const arr = new Object([10,20,30]);

 

[[Prototype]]의 Number, String, Array를 확인할 수 있습니다.

이 래퍼 객체의 Prototype 체인을 통해 해당 타입의 메서드를 사용할 수 있습니다.

원시값의 프로퍼티도 원시 래퍼 객체가 생성되며 Prototype 체인을 통해 메서드를 사용할 수 있는 것이죠.

 

프로토타입 체인을 통해 상속 기능이 구현되고, 자바스크립트의 객체를 더 유기적으로 사용할 수 있게 해줍니다.

자바스크립트가 프로토타입 기반 객체지향 프로그래밍언어라는 것에 대해서 알아보았습니다.

 

 

 


 프로토타입 기반 객체지향 프로그래밍 언어라는 말을 많이 들어봤음에도 프로토타입에 대해 전혀 모르고 있었네요..

코드를 사용하는 것이 다가 아니라, 그 근본을 알고 제대로 사용하는 법을 배우고 있어서 참 뜻깊은 시간이었습니다! 

표로 구분이 힘들어서 그림을 조금 추가해봤는데 누군가에게 도움이 되면 좋겠습니다 :) 

내용이 길어서 2부에서 오버라이딩, 섀도잉, 오버로딩, 정적 프로퍼티 메서드 등등을 알아보겠습니다.

 

1월의 반이 지나가고 있네요. ㅎㅎ 2022년의 24분의 1이 지나가고 있습니다. 모두 화이팅입니다!!

스터디를 진행해주시는 hoon님, 함께 스터디를 듣는 스터디원분들 모두 화이팅입니다!

읽어주셔서 감사합니다. 행복한 코딩라이프되세요~~! 

JavaScript 스터디 팀 러버덕과 함께 합니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/06   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
글 보관함