자바스크립트 프로토타입으로 메서드와 속성 대체하기

자바스크립트의 프로토타입은 생성자 함수의 단점인 중복 멤버 생산을 줄여주는 역할을 합니다. 프로토타입을 사용하면, 반복되는 메서드나 속성을 따로 저장을해서 메모리 사용량을 줄일 수 있습니다.

자바스크립트 생성자 함수로 만든 객체의 단점

생성자 함수가 객체 상수의 단점을 보강하는 것 처럼, 프로토타입은 생성자 함수의 단점을 보완합니다.

생성자 함수로 속성과 메서드의 틀을 만들 때 보통 메서드는 변하지 않는 경우가 많습니다. 하지만 new 키워드로 객체를 만들 때 마다 똑같은 메서드가 메모리에 계속 저장됩니다.

아래 예제를 보면 tesla 객체와 costco 객체를 만들 경우 똑같은 함수인 downdown(); 메서드가 메모리에 각각 저장되므로 중복의 낭비가 발생합니다.

<script>
	//생성자 함수 선언
	function Stock ( name, price )
	{
		this.name = name;
		this.price = price;
		this.downdown = function ()
		{
			this.price *= 0.99;
		};
	}

	//테슬라 객체 생성
	var tesla = new Stock("테슬라", 305871);
	tesla.downdown();
	document.write(tesla.name + " 주가는 " + tesla.price + "로 1% 하락했습니다." + "<br>");

	//코스트코 객체 생성
	var costco = new Stock("코스트코", 268529);
	costco.downdown();
	document.write(costco.name + " 주가는 " + costco.price + "로 1% 하락했습니다." + "<br>");
</script>

결과

테슬라 주가는 302812.29로 1% 하락했습니다.
코스트코 주가는 265843.71로 1% 하락했습니다.

프로토타입을 사용하면, 생성자 함수에서 발생하는 중복 저장 멤버를 하나에만 저장하고, 호출하는 방식으로 메모리를 절약할 수 있습니다.

메서드의 프로토타입 생성

중복이 되어 다른 객체에도 동일한 메서드를 찾아서 생성자 함수 밖으로 뺀 다음 함수를 다시 만들면 됩니다.

이 때 함수명은 this.함수명에서 생성자함수명.prototype.함수명의 형태로 변경됩니다. 나머지 함수 내부의 코드 블록을 설정하는 과정은 동일합니다.

<script>
	//생성자 함수 선언
	function Stock ( name, price )
	{
		this.name = name;
		this.price = price;
	}

	//메서드 프로토타입 선언
	Stock.prototype.downdown = function ()
	{
		this.price *= 0.99;
	};

	//테슬라 객체 생성
	var tesla = new Stock("테슬라", 305871);
	tesla.downdown();
	document.write(tesla.name + " 주가는 " + tesla.price + "로 1% 하락했습니다." + "<br>");

	//코스트코 객체 생성
	var costco = new Stock("코스트코", 268529);
	costco.downdown();
	document.write(costco.name + " 주가는 " + costco.price + "로 1% 하락했습니다." + "<br>");
</script>

결과

테슬라 주가는 302812.29로 1% 하락했습니다.
코스트코 주가는 265843.71로 1% 하락했습니다.

출력 결과는 프로토타입을 사용하지 않은 것과 동일합니다. 하지만 컴퓨터의 메모리 사용 관점에서는 낭비가 줄었습니다.

속성의 프로토타입 생성

생성자 함수에 지정된 속성(property)도 객체마다 동일한 경우가 있다면, 반복을 제거하기 위해서 프로토타입(prototype)으로 지정할 수 있습니다.

예를 들어 아래와 같이 Stock 생성자 함수에서 this.market = "S&P 500" 속성은 매개변수없이 고정된 값입니다. 따라서 객체 생성 마다 쓸데없는 반복으로 메모리 공간을 차지하게 됩니다.

<script>
	function Stock ( name, price )
	{
		this.name = name;
		this.price = price;

		//반복되는 속성(property)
		this.market = "S&P 500";
	}
</script>

메서드처럼 속성도 프로토타입으로 외부로 빼내서 정의하면 됩니다. 마찬가지로 사람 눈에는 출력 결과가 프로토타입을 사용한 것과 사용하지 않은 것이 동일하지만 기계상으로 메모리 사용량이 줄어들게 됩니다.

<script>
	//생성자 함수 선언
	function Stock ( name, price )
	{
		this.name = name;
		this.price = price;
	}

	//속성 프로토타입 선언
	Stock.prototype.market = "S&P 500";

	//객체 생성
	var tesla = new Stock("테슬라", 305871);
	var costco = new Stock("코스트코", 268529);

	//tesla 객체 멤버 모두 출력
	for ( var num in tesla )
	{
		document.write(num + "\t" + tesla[num] + "<br>");
	}

	//costco 객체 멤버 모두 출력
	for ( var num in costco )
	{
		document.write(num + "\t" + costco[num] + "<br>");
	}
</script>

결과

name	테슬라
price	305871
market	S&P 500
name	코스트코
price	268529
market	S&P 500

프로토타입의 개념을 잘 이해하면 내장 객체의 Object 객체나 다른 내장 객체의 메서드가 왜 같이 사용되는지 이해할 수 있습니다.