Front-End

vsoghlv@naver.com

자바스크립트 객체지향 프로그래밍 4

캡슐화는 관련된 여러가지 정보를 하나의 틀안에 담는 것을 말하는데, 중요한 것은 정보의 공개여부이다. C 언어나 Java 에서는 public, private 등을 선언 함으로써 정보 노출 여부를 결정하는데 자바스크립트에서는 지원하지 않는다.

조금 다른 방법을 사용해야 한다.

var Person = function (arg) {
  var name = arg ? arg : "sun";

  this.getName = function () {
    return name;
  };

  this.setName = function (arg) {
    name = arg;
  };
};

var me = new Person();
console.log(me.getName()); //sun
me.setName("Kim");
console.log(me.getName()); //Kim
console.log(me.name); //undefinde

위의 예제를 보면 private 으로 name 을 선언하고, public 메서드로 함수 두개를 선언 하였다. this 객체의 프로퍼티로 선언하면 외부에서 new 키워드로 생성한 객체로 접근할 수 있는데 var 로 선언한 멤버에는 외부에서 접근이 불가능하다.

하지만 그 안에서는 public 메서드가 클로저 역할을 하면서 name 에 접근이 가능하다. 이것이 자바스크립트에서 기본적으로 가능한 정보 은닉이다.

위의 코드를 조금 더 깔끔하게 정리해보자.

var Person = function (arg) {
  var name = arg ? arg : "sun";
  return {
    getName: function () {
      return name;
    },
    setName: function (arg) {
      name = arg;
    },
  };
};

var me = Person();

Person 함수를 호출하여 객체를 반환받는데 이 객체에 Person 의 private 멤버에 접근할 수 있는 메서드들이 담겨있다. 사용자는 반환된 객체로 메서드를 호출할 수 도 있고 private 멤버에 접근도 가능하다.

여기서 주의할 점이 있는데 접근하는 private 멤버가 객체나 배열이면 얕은 복사로 참조만을 반환하므로 사용자가 이를 쉽게 변경할 수 있다.

때문에 보통의 경우, 객체를 반환하지 않고 객체의 주요 정보를 새로운 객체에 담아서 반환하는 방법을 많이 사용하는데, 만약 꼭 객체가 반환되야 하는 경우 깊은 복사로 복사본을 만들어 반환하는 것이 좋다.

위의 예제를 보면 단점이 하나 있는데 사용자가 반환받는 객체는 Person 함수 객체의 프로토타입에는 접근할 수 없다는 단점이 있다. 이를 보환하기 위해서는 객체가 아닌 함수를 반환하는 것이 좋다.

var Person = function (arg) {
  var name = arg ? arg : "sun";

  var Func = function () {};
  Func.prototype = {
    getName: function () {
      return name;
    },
    setName: function (arg) {
      name = arg;
    },
  };
  return Func;
};

위의 예제에서는 Func가 클로저가 되고 이 함수가 참조하는 name 프로퍼티는 자유 변수가 된다. 따라서 사용자는 name 에 접근이 불가능하다.