본문 바로가기

자바스크립트 문법 (10) 객체지향 Class

by Recstasy 2019. 5. 14.

(10) 객체지향 클래스


ES2015 버전부터 자바스크립트에서 클래스를 사용할 수 있게 되었다. 자바스크립트는 객체지향 언어에 존재하는 class 구문이 없다. 대신, 객체 인스턴스를 활용하는 프로토타입 객체가 있다. ES2016부터 겉보기에 class 문법을 사용할 수 있지만 내부에 돌아가는 구조는 프로토타입 객체 방식이다. 하지만 이 마저도 IE 7이전 버전에는 적용되지 않는다. 향후 3~4년간 웹 브라우저가 완벽하게 ES2015문법에 적용하기 전까지는 기존의 프로토타입과 인스턴스 객체생성 방식을 알아둬야 할 필요가 있다.

 

1 『프로토타입』

 프로토타입이란 뭘까? 사전적인 의미로는 '모형'이다. 어떠한 제품을 양산하기 위한 '시제품' 정도로 이해할 수 있다.



 가령, 신발을 생산하는 공장을 짓는다면, 각 사이즈에 맞는 '틀'부터 만들어야 한다.(대량생산을 위해서) 발 모양과 사이즈, 디자인에 맞는 나무모형을 제작한 후에 가죽을 가열하여 신발모양을 만든다. 여기서 신발제작에 사용하는 '나무모형'은 자바스크립트에서 '프로토타입'정도로 생각할 수 있다.


 다른 언어에서는 프로토타입을 '클래스'라 명하고, 클래스를 상속(복사)받은 후에 기능을 추가하거나 빼서 각 프로젝트에 맞는 객체를 생성한다.


ES2015버전이 도입되기 전까지, 자바스크립트에서는 클래스가 없었다. 이 때문에 프로토타입(모형)을 만들고, 이를 복사(인스턴스)하여 사용하였다. 사실상 프로토타입을 생성하고, 이용하는 것을 클래스를 이용하는 것이라 불러도 무방하다.


2 『클래스 정의』


[예제]

var Blogpost = function(name,time ) { 

this.name = name;

this.time = time;

this.conduct = function( ) {

return this.name + this.time;

}

 };


var myBlog = new Blogpost( 'mogl3d' , '20171117 );

console.log( myBlog.conduct( ) );


myBlog.getTime( ) = function( ){

return this.time;

}


console.log( myBlog.getTime( ) );


// 결과: mogl3d20171117

// 결과: 20171117


프로토타입에서 인스턴스를 만들면, 각각의 객체에 따라 다른 복사본의 공간이 만들어진다.


[예제]

var Members = function( fistname, lastname ){

this.firstname = firstname;

this.lastname = lastname;

this.getName = function( ){

                              return this.firstname +  this.lastname;

                                 }

      }

var name1 = new Members( '이' , '예린' );

console.log( name1.getName( ) );    // 결과:  이예린


var name2 = new Members( '황' , '수창' );

name2.getName2 = function( ) {         // getName2 매서드 추가하기

return this.firstname + this.lastname;

}


console.log( name2.getName2( ) );  // 결과: 황수창

console.log( name1.getName2( ) );  // Uncaught Type error


위의 코드에서 똑같은 프로토타입 객체 Members를 인스턴화한 객체들이 name1 과 name2이다.지만 name1과 name2는 Members 프로토타입을 참조만 하고 있을뿐, 각자 복사한 영역은 다르다.


가령, 특정 TV를 컨트롤 할 수 있는 리모콘이 2개 있는 상황이라면, 우리는 리모콘 조작을 통해 TV기능을 이용한다. 이때 리모콘(인스턴스 객체)으로 조작하는 TV(프로토타입 객체)는 같다고 할 수 있지만, TV가 같다고 리모콘도 같다고 할 수는 없다.


name1과 name2는 리모콘이다.

name2.getName2( )라는 매서드는 name2라는 리모콘에 새로 저장된 기능이다. 

TV나 name1에서 아무리 getName2( ) 기능을 활용하려 해도 찾을 수 없다.


3 『프로토타입, this』

 자바스크립트에서 this는 특별하다. 함수라면 함수 그 자신을 가리키고, 생성자나 객체 자신을 뜻하기도 한다. this는 이벤트, 메소드, 함수, 생성자에서 많이 사용되지만, 프로토타입에서 중요한 쓰임새는 call / apply 메소드에 있다.


call / appy 메소드는 둘 다 함수가 제공하는 멤버로, 그 함수를 호출한다.

call과 apply의 차이점은, 함수의 인수에 데이터를 건네는 방식에 있다.

call 메소드는 개별값으로 지정하는 데 반해 apply 메소드는 배열로 전달한다.



[예제]

var data = 'ALL'

var obj1 = { data : 'javascript'  }

var obj2 = { data : 'node.js' }


function dev( ) {

console.log( this.data );

}


dev.call ( null ); // 결과 : ALL

dev.call ( obj1 ); // 결과 'javascript'

dev.call ( obj2 ); // 결과 'node.js'


dev 함수의 console.log( ) 안에 this키워드가 있다. 여기서 this가 가리키는 값은 call 메소드에 의해 들어온 인수의 객체다. 따라서 call ( )인수값에 어떠한 객체가 오는지에 따라 this가 가리키는 값이 달라지고, console.log 결과값도 달라진다.


call( )메소드를 활용한 배열 예시를 살펴보자.



[예제]

function data( ) {

var args = Array.prototype.slice.call( arguments );

console.log( args.join( '/ ' ) );

}

data( 'Angular' ,'Electron' ,'Meteor' );    // 결과: Angular/Electron/Meteor


위의 예제에서는 인수로 들어온 arguments값을 배열로 자른 후에 (slice) call 메소드를 활용하였다. 여기서 call메서드는 arguments 객체를 가리킨다. 


* 참고사항:: 생성자 강제호출 방어


[예제]

var Members = function( firstName, lastName ){

this.firstName = firstName;

this.lastName = lastName;

}

var name = Members( '조세' ,'무리뉴' );    // 'new'를 붙이지 않은 실수를 했다.


console.log(name); // 결과: undefined

console.log(firstName); // 결과: 조세

console.log(name.firstName); // 결과: Error


위와 같이 프로토타입을 인스턴스화 할 때 'new'를 빼먹는 실수를 할 수 있다. 이렇게 되면, firstName을 글로벌 변수로 인식해버린다. 따라서 반드시 아래처럼 생성자를 작성할 때 new를 붙여야 한다.



var Members = function(firstName,lastName){

if( !(this instanceof Members )) {

return new Members(firstName,lastName);

}

this.firstName = firstName;

this.lastName = lastName;

};




댓글

최신글 전체

이미지
제목
글쓴이
등록일