반응형

 객체 지향 프로그래밍은 자바나 C++같은 언어에서는 클래스 기반으로 이루어진다. 객체지향 프로그래밍에서는 상속을 통해 코드 재사용성을 높이고 캐스팅의 명세를 제공한다. 자바스크립트는 클래스를 제공하지 않고 프로토타입 기반의 상속을 제공하는데, 객체의 자료구조, 메서드 등을 동적으로 바꿀 수 있다. 이번 포스팅에서는 자바스크립트의 객체지향 프로그래밍 방법에 대해서 이야기 한다.


1. 의사 클래스 방식

 함수를 이용하여 new 키워드로 객체를 생성하는 방법이다. 의사 클래스 방식이라는 이름은 클래스처럼 객체를 생성하는 것처럼 보이기 때문이다. 

 함수 객체를 생성할 경우 Function 생성자는 다음과 같은 코드를 실행한다. this.prototype = {constructor : this} ; 즉 생성한 함수 객체의  prototype  객체를 만드는데, 이때 자신을 가르키는 constructor라는 프로퍼티를 설정하는 것이다.

 new 연산자를 사용하여 생성자 호출 패턴으로 함수가 호출되면 다음과 같은 형태로 구현될 수 있다.

Function.method('new',function(){

var that=Object.create(this.prototype);

var other=this.apply(that,argument);

return (typeof other==='object' && other) || that; 

});

 

1) 생성자 프로토타입을 상속받는 새로운 객체 생성

2) this 를 새로운 객체로 바인딩하여 생성자 호출

3) 반환값이 객체가 아니면 새로운 객체로 리턴



 이 코드에서 보면, 생성자 함수에서 명시적으로 객체를 반환하지 않는다고 하여도, 생성자 함수의 this에 적용된 객체를 반환하게 된다. 또한 생성자 함수에서 기본타입을 반환할 경우에도 새로운 객체를 반환하게 되는 이유를 알 수 있다. 생성자 함수의 prototype 에 메소드를 추가함으로써, 재활용 가능한 함수들을 추가할 수 있다.

 하지만 모든 메소드가 public이 되며 부모 메소드로 접근할 수가 없다. 또한 new 빼고 호출할 경우에는 생성자 함수 내부의 this가 전역 객체에 바인딩 되어 전역 객체를 오염시킬 수 있다. 클래스 기반 프로그래밍에 익숙한 프로그래머들에게는 편리해보이지만, 자바스크립트의 진정한 특성을 이용한 다른 방법들이 존재하며, new 기반의 상속은 피하는 것이 좋다고 한다.


2. 프로토타입 방식

 더글라스 크록포드는 넘겨받는 객체를 프로토타입으로 하는 새로운 객체를 생성하는 메소드를 다음과 같이 소개하였다.

if (typeof Object.create !== 'function'){

Object.create = function(o){

var F=function(){};

F.prototype=o;

return new F();

};

  이렇게 객체를 생성하면, 생성된 객체는 넘겨받는 객체 o 의 메소드와 속성에 접근 가능하게 된다. 물론 자신의 메소드와 속성을 만들수도 있다. ECMAScript 5에서는 Object.create() 함수로 제공한다.

3. 캡슐화

 캡슐화는 관련된 여러 정보를 하나의 틀 안에 담는 것으로, 정보 은익 개념이 중요하다. 앞의 두가지 방식에는 private 속성을 가질수 없다. 자바스크립트에서는 private 키워드 자체가 존재하지 않는다. 다만 클로저를 이용해서 속성을 감출 수 있다. 더글라스 크록포드는 다음과 같은 private 변수를 가지는 객체 생성 방법을 제안하였다.

var constructor = function(spec, my){

var that, private변수들;

my = my || {};

my에 숨기고자하는 변수들을 추가;

that = 새로운 객체;

my에 접근하는 메소드들을 that 에 추가;

return that;

}; 

 my 객체는 상속 연결상에서 생성자와 공유하게 되는 비밀들을 담는 컨테이너가 된다. 위 코드를 이용한 간단한 예는 다음과 같다.

var testCap=function(spec){

var that={};

var my={};

my.name=spec.name||'unknown';

my.count=0;

that.getName=function(){

return my.name;

}

that.setName=function(inName){

my.name=inName;

}

that.inc=function(){my.count++;};

that.dec=function(){my.count--;};

that.getCnt=function(){return my.count;};

return that;

 [실행 예]


> var catObj=testCap({name:'hello'})

undefined

> catObj.getName()

'hello'

> catObj.inc()

undefined

> catObj.getCnt()

1

> catObj.name

undefined





 이 패턴에서는 super 메소드를 다룰수 있는 방법을 제공한다. 다음의 코드에서 superior이 반환하는 메소드는 함수의 속성이 변경되도라도 원래 함수를 호출할 수 있도록 해준다.

function (target, name){

var that=target;

var method=that[name];

return function(){

return method.apply(that,arguments);

};

}); 

 위코드를 이용한 간단한 예는 다음과 같다.

var testCap2=function(spec){

var that=testCap(spec);

var superGet=superior(that,'getName');

that.getName=function(){

return superGet()+" world";

}

return that;

 [실행 예]


> var catSuper=testCap2({name:'hello'})

undefined

> catSuper.getName()

'hello world'

>



반응형
Posted by alias
,