(11) 프로토타입 객체
지난 포스팅에서는 프로토타입 객체를 인스턴스로 사용하는 과정을 소개했다. 하지만 자바스크립트에서 프로토타입 객체 방식을 사용할 경우, 치명적인 단점이 있다. 범용 프로그래밍 언어이라 할 수 있는 자바나 파이썬과 달리 자바스크립트는 태생 자체가 웹 개발을 위해 만들어졌다. 자바스크립트가 배우기 쉬운 이유는 따로 메모리 관리를 할 필요가 없기 때문이다.
웹 환경이 개선되고, 하드웨어 속도가 빨라지면서 웹 개발은 점차 대규모 프로젝트로 진행되고 있다. 이제 자바스크립트도 메모리 관리를 해야하는 시점이 오고 있는데, 프로토타입 객체에서 인스턴스를 사용하는 방식은 메모리 관리에 쥐약이다. 프로토타입 객체를 계속 인스턴스해서 변수에 담게 되면 '메모리 낭비'가 발생하기 때문이다.
가령, 아래와 같은 방식은 메모리가 낭비된다.
[예제]
var Member =
function( firstname, lastname ) {
this.firstname = firstname;
this.lastname = lastname;
this.getName = function( ){
return this.firstname + ':' + this.lastname;
}
}
만일 Member객체에 대한 프로토타입을 생성(인스턴스)한다면, 해당 인스턴스를 불러올 때마다 getName과 같은 메서드도 계속 호출된다. getName 메소드를 사용할 필요가 없는 var address 라는 변수에도 getName 메서드는 귀신처럼 따라붙는다. 따라서 인스턴스를 할 때마다 자신도 모르게 낭비를 계속 하게 된다.
1 『프로토타입 선언』
메모리 낭비를 방지하기 위해서는 다음과 같은 prototype 명령어가
필요하다. 필수 매서드나 데이터가 아닌 부분은 원본 프로토타입 객체에 기입하지
않는 것이다.
var Member = function( ){
}
우선 프로토 타입으로 객체선언만 한다. 이후, Member 프로토타입에 아래처럼 프로퍼티를 prototype으로 선언한다.
Member.prototype.firstName = '모글'
Member.prototype.getName = function(
){
return this.firstName;
}
var name1 = new Member( );
var name2 = new Member( );
console.log( name2.firstName ) // 결과: '모글'
console.log( name1.firstName ); // 결과: '모글'
prototype으로 firstName과 getName 메서드를 선언하지 않았더라면, 에러가 나거나, name1.firstName이라고 입력을 해줘야만 값이 나온다. 하지만 prototype으로 선언을 한다면, default값으로 선언한 값이 호출되며, 프로토타입 객체를 인스턴스화할 때 prototype으로 선언한 메서드나 프로퍼티는 메모리가 읽지 않는다.
결과적으로 호출이 되었을 때만 prototype 선언 객체가 전달되기 때문에 메모리를
절약하고 속도를 올릴 수 있다. 만일 prototype으로 선언된 원본 객체의 내용을 바꾼 인스턴스를 이용하고
싶다면, 아래와 같이 바꿔준다.
var name3 =
new Member( );
name3.brand = '신라면'
이런 방식으로 메모리를 절약하면서 인스턴스를 사용할 수 있다. 이를 위해 자바스크립트에서는 아래의 룰을 정했다.
- 프로퍼티의 선언 => 생성자
- 메소드의 선언 => 프로토타입
2 『프로토타입 삭제』
프로토타입의 삭제는 delete 명령어로 할 수 있다.
[예제]
var Car = function( ) { };
Car.prototype.brand = '쉐보레';
var truck = new Car( );
var sedan = new Car( ); ----------> ①
console.log( truck.brand + ' | ' + sedan.brand ); // 결과 : 쉐보레 | 쉐보레
sedan.brand =
"현대";
console.log( truck.brand + ' | ' + sedan.brand ); // 결과 : 쉐보레 | 현대
delete truck.brand; ------------> ②
delete
sedan.brand;
console.log( truck.brand + ' | ' + sedan.brand ); // 결과: 쉐보레 | 쉐보레
①에서, truck과 sedan의 브랜드는 암묵적 참조에 의해 '쉐보레'가 되었다.
②에서, truck과 sedan의 brand를 모두 삭제하면, 인스턴스로 '현대'를 집어넣은 brand 프로퍼티만 삭제된다. 즉, delete를 하더라도 인스턴스에 있는 값만 삭제되는 것이다.
프로토타입 객체에 있는 값 자체를 삭제하려면, delete Car.prototype.brand 라고 입력하면
된다. 만일 Car 프로토타입에 있는 brand를 prototype으로 삭제해버리면
모든 인스턴스에 영향을 미친다.
3 『객체 리터럴 값으로 프로토타입 정의하기』
프로토타입을 선언하는 방식으로 prototye.메소드 형태로 계속 선언하려면 중복이 발생하고, 비효율적이다. 따라서 다음과 같이 객체 리터럴 방식으로 선언하면 효율을 높일 수 있다.
[예제]
var Car =
function( brand, color ) {
this.brand = brand;
this.color = color;
} ;
Car.prototype.getCar = function( )
{
return
this.brand + ' ' + this.color;
}
Car.prototype.getSell = function( )
{
return this.brand + ' ' + this.color + '판매합니다'
}
메소드를 정의할 때마다 prototype을 붙이면 엄청 비효율적이다.
따라서 아래처럼 작성한다.
var Car =
function( brand, color ){
this.brand = brand;
this.color = color;
};
Car.prototype
= {
getCar : function( ) {
return this.brand + ' ' +this.color;
},
getSell : function( ) {
return this.brand + ' ' +this.color +'판매합니다.';
}
}
'코드 스터디' 카테고리의 다른 글
자바스크립트 문법 (13) 객체의 타입 판정하기 (0) | 2019.05.17 |
---|---|
자바스크립트 문법 (12) 객체의 상속(프로토타입 체인) (0) | 2019.05.16 |
자바스크립트 문법 (10) 객체지향 Class (0) | 2019.05.14 |
자바스크립트 문법 (9) 클로저 (0) | 2019.05.13 |
자바스크립트 문법(8) 고차함수 (0) | 2019.05.07 |
댓글