개발계발/Javascript

Javascript 객체 지향[1] - this/constructor/prototype

냥냥친구 2019. 6. 29. 15:47

자바스크립트는 객체지향 스크립트 언어이다.

객체지향을 내 기준에서 간단하게 설명하면 자주 사용하는 걸  구조화해놓는 것이다.

그러면 필요할 때마다 만들지 않아도 되고 이미 만들어진 걸 가져다 쓰기만 하면 된다.

여기서 미리 만들어 놓는다는 개념이 자바스크립트에서는 함수,클래스가 된다.

 

자바스크립트가 객체지향 언어인 만큼 객체 관련 기능들을 제공한다. 이번에는 this, constructor, prototype을 알아본다.

*생활 코딩 javascript 객체지향 내용을 공부하며 정리한 것입니다.

 

1.this

 - 자신을 가리키는 특수한 키워드로 오브젝트, 클래스 안에서 선언한 변수 및 함수를 자기 안에서 호출할 때 사용한다.

 

var fisrt = 5;
var second = 10;
var kim = {
	name:"kim",
    first:10,
    second:20,
    sum:function(){
    	return this.first+this.second;
        }
};

var lee = {
	name:"lee",
    first:10,
    second:20,
    sum:function(){
    	return first+second;
        }
};
    
 console.log("kim.sum()", kim.sum()); //kim.sum() 30
 console.log("lee.sum()", lee.sum()); //lee.sum() 15

위 코드를 보면 kim은 오브젝트로써 name과 점수를 나타내는 first, second, 그리고 그 합계를 구하게 해주는 sum()이 있다. kim의 합계를 알고 싶을 때는 kim의 메서드 함수인 sum()을 호출해서 확인하면 된다. (= kim.sum())

sum()을 살펴보면, first, second 변수를 더한 값을 리턴하는데, 이 때 first, second 앞에 this가 붙어서 객체 안의 first, second 임을 명시하고 있다. 그렇기 때문에 리턴 값은 30 이 된다.

반면에, lee의 sum() this 없이 first와 second의 합을 리턴하고 있는데 결과 값은 30이 아닌 15가 된다.

lee 내의 first와 second가 아닌 전역변수의 fisrt, second의 합을 구했기 때문이다.

 

2. 생성자(constructor)

만약 kim,lee 처럼 똑같은 구조를 가진 변수가 1억 개 필요하다고 한다면 1억 번 다 똑같이 정의해야 할까? 결국 1억 번을 다 정의했는데 3번째 점수인 third가 생긴다면 각각의 변수에 third를 추가하는 1억 번의 작업을 해야 할까? 같은 구조의 변수라면 구조를 미리 정의해놓고 가져다 쓸 수 있는데 그 방법이 constructor이다.

function Person(name, first, second){
    this.name=name;
    this.first=first;
    this.second=second;
    this.sum = function(){
        return this.first+this.second;
    }
}

var kim = new Person('kim', 10, 20);
var lee = new Person('lee', 10, 10);
console.log("kim.sum()", kim.sum()); //kim.sum() 30
console.log("lee.sum()", lee.sum()); //lee.sum() 20

먼저, 같은 구조를 정의하는 Person 함수를 만든다. 구조는 같아도 이름,점수는 다르기 때문에 값을 받는 파라미터도 추가한다. 그리고 Person 앞에 new를 붙이고 변수를 선언하면 된다. new를 붙이면 새로운 객체를 생성하는 생성자 함수가 된다.  즉, 함수로 객체를 생성한다는 말은 생성자 함수로 선언한다와 같다고 보면 된다.

third를 추가하고 싶으면 Person 내에다가 한 번만 추가하면 된다.

 

3. prototype

앞서 정의한 Person 함수에 new를 붙이면 함수로 객체(kim, lee)를 생성할 수 있었다. 그런데 생성자 함수를 호출할 때마다 공통적으로 사용하는 sum()을 계속 생성하는데, 이는 메모리를 차지하게 된다. 공통적으로 사용하는 함수는 한 번만 선언하어 좋지 않을까? 이럴 때 사용해 볼 수 있는 것이 prototype이다.

function Person(name, first, second, third){
    this.name=name;
    this.first=first;
    this.second=second;   
}
 
Person.prototype.sum = function(){
    return 'prototype : '+(this.first+this.second);
}
 
var kim = new Person('kim', 10, 20);
kim.sum = function(){
    return 'this : '+(this.first+this.second);
}
var lee = new Person('lee', 10, 10);
console.log("kim.sum()", kim.sum());
console.log("lee.sum()", lee.sum());

위 코드처럼 prototype을 사용해 sum 함수를 정의하면 된다. 그런데 저렇게 하면 Person에 sum()이 추가돼서 똑같아지는 거 아닌가 생각했는데, 확인해보니 아래와 같았다.

sum을 추가하고 나서 다시 확인해봤을 때 sum이 추가되지는 않았다...! 호오...

하지만 Person의 prototype을 확인해 보면, sum()이 정의되어 있다.

이 부분을 간단하게 설명하면 함수를 생성할 때 함수의 prototype object도 같이 생성되는데 생성자 함수로 만들어진 객체도 이 prototype에 접근할 수 있다. 그렇기 때문에 prototype의 속성을 사용할 수 있는 것이다. 여기서는 sum()이 된다.

생성자 함수로 객체가 여러 개 만들어져도 하나의 prototype을 공유하고 있기 때문에 공통적으로 적용할 수 있고 메모리를 객체 개수만큼 사용하지 않는다. 

prototype은 내용이 많아 보여서 좀 더 알아봐야겠다.