본문 바로가기
자바스크립트(JavaScript)/자바스크립트

[JavaScirpt] 객체 생성자 함수(Object Contructor Function), 프로토타입(prototype)

by yerica 2024. 8. 5.
모든 객체는 프로토타입(prototype)으로부터 생성자 속성을 상속받는다. 

1. 객체의 생성

자바스크립트에서는 다음과 같은 방법으로 객체를 생성한다.
 
1. 리터럴 표기(literal notation)를 이용한 방법
리터럴 표기 법은 프로퍼티의 이름과 값을 콜론(:)으로 연결하고, 쉼표(,)를 사용해 다른 프로퍼티와 구분하는 방식이다.
var 객체이름 = {
    프로퍼티1이름 : 프로퍼티1의값,
    프로퍼티2이름 : 프로퍼티2의값,
    ...
};​

2. 생성자 함수(constructor function)를 이용한 방법

new 연산자를 사용하면 객체를 생성하고 초기화 할 수 있다.

이때 사용되는 메소드를 생성자(constructor)라고 하며, 이 메소드는 새롭게 생성되는 객체를 초기화하는 역할을 한다.

자바스크립트에서 제공하는 생성자(Object, Math, Array 등)을 사용해도 되고 (내장 객체 생성 참고),
사용자가 직접 객체 생성자 함수(object constructor function)를 작성하여 사용할 수도 있다.

var 참조변수 = new 생성자 함수();

3. Object.create() 메소드를 이용한 방법
Object.create(프로토타입객체[, 새로운객체의프로퍼티1, 새로운객체의프로퍼티2, ...]);​

위와 같은 방법으로 생성된 객체는 메모리에 인스턴스(instance) 객체로 저장된다. 

객체 리터럴 방식과 내장 객체 생성자 함수 방식으로 객체를 생성하는 것은 속성값만 다른 여러 개의 객체를 생성할 때 불편하고 비효율적이다. 동일한 속성을 갖는 객체임에도 불구하고 매번 다시 작성해야하기 때문이다.
이러한 상황에서 사용하는 것이 객체 생성자 함수 (object constructor function) 이다.

2. 객체 생성자 함수 ( Object Contructor Function )

객체 생성자 함수에서는 this라는 키워드를 함께 사용한다.
this는 쓰이는 곳에 따라 가리키는 것이 다른데, 이곳에서는 생성자 함수가 생성할 인스턴스를 가리킨다.
※ 객체 생성자 함수를 작성할 때에는 관례상 이름의 첫 문자만을 대문자로 작성한다.
// 객체 생성자 함수 기본형
        function 함수명(매개변수1, 매개변수2...){
            this.속성명 = 속성값;
            this.함수명 = function(){ 자바스크립트 코드; }
        }
        
// 객체 생성자 함수 호출문(new 라는 키워드는 반드시 붙어야 한다.)
        let 참조변수 = new 함수명(); 
        
// 이 틀을 안전하게 보관하려면 let 보단 const를 쓰는 것이 안전하다.
예시로 아래와 같이 사용자의 정보를 수집하는 함수를 만들어보자.
function UserInfo(name, height, weight) {
        //사용자의 이름을 this(객체)의 userName 속성에 할당한다.
        this.userName = name;
        this.userHeight = height;
        this.userWeight = weight;
        // 사용자의 정보를 단순 출력해주는 함수.
        this.getInfo = functon() {
          let str = "";
          str += "이름 : " + this.userName + " , ";
          str += "키 : " + this.userHeight + " , ";
          str += "몸무게 : " + this.userWeight + "<br/>";
          return str;
        };
}
아래는 참조변수를 선언하고 동시에 생성된 객체의 주소를 참조변수에 저장하는 모습이다.
참조변수 kim은 새로 생성되는 instance를 가리킨다.
그리고 프로퍼티 값은 함께 선언된 값을 말한다.  (참조변수와 인스턴스 참고)
let kim = new UserInfo("김땡땡", "175", "65");
console.log(kim);
document.write(kim.getInfo(), "<br/>");

 

콘솔창에서 변수 kim을 확인하면 아래와 같다.

kim의 프로퍼티인 getInfo()를 화면에 출력해보면 아래와 같이 출력된다.


3. 생성자 속성 상속 ( inheritance )

상속(inheritance)이란 새로운 클래스에서 기존 클래스의 모든 프로퍼티와 메소드를 사용할 수 있는 것을 의미한다.

상속을 통해 새로운 프로그램의 요구에 맞게 기존 클래스를 수정하여 재사용할 수 있다.
또한, 클래스 간의 종속 관계(부모, 자식과 같은)를 형성함으로써 객체의 관계를 조직화할 수 있는 장점이 있다.
따라서 이러한 상속은 추상화, 캡슐화와 더불어 객체 지향 프로그래밍을 구성하는 중요한 특징 중 하나이다.

하지만 C#이나 C++과 같은 클래스 기반(class-based)의 객체 지향 언어와는 달리 자바스크립트는 프로토타입 기반(prototype-based)의 객체 지향 언어이다.
프로토타입 기반이기 때문에 상속의 개념이 클래스 기반의 객체 지향 언어와는 약간 다르다.
자바스크립트에서는 현재 존재하고 있는 객체를 프로토타입으로 사용하여, 해당 객체를 복제하여 재사용하는 것을 상속이라고 한다.
var o = {};
o.constructor === Object; // true

var o = new Object();
o.constructor === Object; // true

var a = [];
a.constructor === Array; // true

var a = new Array();
a.constructor === Array; // true

var n = new Number(3);
n.constructor === Number; // true

4. 프로토타입 ( prototype )

프로토타입의 사전적인 의미는 '원형'이다. "원래의 형태" 를 뜻하는데 유전자와 비슷하다고 생각하면 쉽다.
자바스크립트의 모든 객체는 프로토타입(prototype)이라는 객체를 가지고 있으며, 
모든 객체는 그들의 프로토타입으로부터 프로퍼티와 메소드를 상속받는다.

이때 상속되는 정보를 제공하는 객체를 프로토타입(prototype)이라고 한다.

5. 프로토타입 체인 ( prototype chain )

자바스크립트에서는 객체 이니셜라이저를 사용해 생성된 같은 타입의 객체들은 모두 같은 프로토타입을 가진다.
또한, new 연산자를 사용해 생성한 객체는 생성자의 프로토타입을 자신의 프로토타입으로 상속받는다.
프로토타입이 상속되는 가상의 연결 고리를 프로토타입 체인(prototype chain)이라고 합니다
var obj = new Object(); 
// obj의 프로토타입은 Object.prototype

var arr = new Array();  
// arr의 프로토타입은 Array.prototype 및 Object.prototype

var date = new Date();  
// date의 프로토타입은 Date.prototype 및 Object.prototype
Object.prototype 객체는 어떠한 프로토타입도 가지지 않으며, 아무런 프로퍼티도 상속받지 않는다.
Object.prototype 객체가 프로토타입 체인 중에서 가장 상위에 존재하는 프로토타입이기 때문이다.
따라서, 자바스크립트의 모든 객체와 내장된 모든 생성자, 사용자 정의 생성자는 Object를 프로토타입으로 가지며 상속받는다.

6. 프로토타입의 생성

프로토타입을 생성하는 가장 기본적인 방법은 객체 생성자 함수(object constructor function)를 사용하는 것이다.
생성자 함수를 작성하고 new 연산자를 사용해 객체를 생성하면, 같은 프로토타입을 가지는 객체들을 생성할 수 있다.
// 객체 생성자 함수 기본형
        function 함수명(매개변수1, 매개변수2...){
            this.속성명 = 속성값;
            this.함수명 = function(){ 자바스크립트 코드; }
        }
        
// 객체 생성자 함수 호출문
        let 참조변수 = new 함수명();

 

아래 예시를 보면 객체 kim은 생성자 함수인 UserInfo를 참조하는 변수이다.
new 연산자를 사용하여 만들어 졌기 때문에 객체 kim은 UserInfo라는 프로토타입을 가지게 된다.
// 사용자 정보에 관한 생성자 함수를 작성
function UserInfo(name, height, weight) { 	

        //이름에 관한 프로퍼티
        this.userName = name;	
        //키에 관한 프로퍼티
        this.userHeight = height;	
        //몸무게에 관한 프로퍼티
        this.userWeight = weight;		
        
        //정보를 단순 나열하기 위한 프로퍼티
        this.getInfo = functon() {			
          let str = "";
          str += "이름 : " + this.userName + " , ";
          str += "키 : " + this.userHeight + " , ";
          str += "몸무게 : " + this.userWeight + "<br/>";
          return str;
        };
}

//객체 kim은 UserInfo라는 프로토타입을 가진다
let kim = new UserInfo("김땡땡", "175", "65");

7. prototype 속성 추가

객체 생성자 함수로 객체를 생성하여 사용하면 생성한 만큼 데이터에 함수가 등록된다.
이렇게 여러개의 함수를 등록하면 메모리 공간을 많이 차지하여 메모리를 낭비하게 된다.
이럴 때 객체 생성자 함수에 프로토타입(prototype) 속성을 사용하여 함수를 등록하면 메모리 낭비를 줄일 수 있다.
//기본형
function 함수명1(매개변수...){

	// 객체의 프로퍼티(속성)
    this.속성명 = 속성값;		    
    
    //객체의 프로토타입 메서드
	함수명1.prototype.함수명2 = function(){자바스크립트 코드;}  
}

// 실행
let 변수명 = new 함수명1();		

//프로토타입으로 만들어 둔 메서드 출력
변수명.함수명2();
UserInfo함수에서 getInfo를 prototype 속성을 적용하면 this.getInfo에서 UserInfo.prototype.getInfo라고 바뀐다.
function UserInfo(name, height, weight) {
        this.userName = name;
        this.userHeight = height;
        this.userWeight = weight;
        
        UserInfo.prototype.getInfo = functon() {
          let str = "";
          str += "이름 : " + this.userName + " , ";
          str += "키 : " + this.userHeight + " , ";
          str += "몸무게 : " + this.userWeight + "<br/>";
          return str;
        };
}

let kim = new UserInfo("김땡땡", "175", "65");
console.log(kim);
콘솔창으로 확인해보니 객체 kim의 내용에서 getInfo의 값이 사라진 것을 볼 수 있다.
실제로 getInfo의 값이 존재하지 않은것은 아니고 언제든지 프로토타입에서 가져올 수 있지만 당장에는 필요하지 않으니 가져오지 않은 것이라고 보면 된다.

kim.getInfo()의 값을 가져오고 싶으면 아래와 같이 출력하면된다.
이렇게 출력되었을 때 재미있는 점은, 화면에 출력하라고 했기 때문에 화면에만 출력된다는 것이다.
콘솔창에는 위와 동일하게 내용이 보이지 않는것을 확인할 수 있다.
document.write(kim.getInfo(), "<br/>");


내용정리 및 추가 설명


1. 객체 생성자 함수로 객체를 생성하면 선언한 만큼 데이터에 함수가 등록되고 각기 다른 데이터 주소를 가진다.

2. 이렇게 메모리에 공간을 차지하는 고유한 객체를 인스턴스(instance)라고 한다.

3. 동일한 프로퍼티를 활용하여 다양한 인스턴스를 만들고 싶다면 객체 생성자 함수를 사용하면 된다.

3. 생성자 함수명은 일반 함수와 구별하기 쉽도록 대문자로 시작하는 것이 관례이다.

4. 생성자 함수 내의 this는 생성자 함수가 생성할 인스턴스를 가리킨다.

5. this 는 화살표 함수가 누구인지 모른다. 그렇기 때문에 사용하려면 화살표 함수 대신 익명함수를 사용해야한다.

6. this에 바인딩 되어있는 프로퍼티와 메서드는 public(외부에서 참조 가능)하다.

7. 생성자 함수 내에서 선언된 일반 변수는 지역변수로 private(외부에서 참조 불가능)하다

8. 매개변수에 대입될 인수자리에 문자형 숫자가 들어가도 생성자 함수 내에서 연산이 가능한 이유는 자바스크립트에서 자동으로 변환하기 때문이다. 원래는 오류가 나는것이 맞다. 이러한 결과를 방지하기 위해서 타임 스크립트 같은 정적 타입 언어를 쓰는것이다.

 

 

참고

1. TCP - prototype

2. TCP - object create

3. 5kdk.tistory - 객체응용 - 생성자 함수(feat. 인스턴스)

4. mdn - Object.prototype.constructor

5. yongchan_0312 - 인스턴스와 참조변수