ES2015의 Class에서 개인 인스턴스 변수

Symbols 를 이용합니다. 예를 들어 Person 클래스에서 「이름」 「연령」을 private 로 하고 싶은 경우는 다음과 같이 합니다.

person.es6
const propName = Symbol();
const propAge = Symbol();

/**
 * Person class
 */
class Person {
  /**
   * @constructor
   * @param {string} name
   * @param {number} age
   */
  constructor(name, age) {
    this[propName] = name;
    this[propAge] = age;
  }
}

export default Person;

변수 propNamepropAage는 고유하며 다른 방법으로 동일한 값을 생성할 수 없으며 이 파일 내에서만 액세스할 수 있습니다.

이 예에서는 인스턴스 생성 시 '이름'과 '연령'을 설정한 후,

some.es6
import Person from './person.es6';

const person = new Person('Yamada', 45);

'이름' 또는 '연령'에 액세스할 수 없습니다.

「이름」 「연령」을 Person 클래스내의 메소드만으로 이용하는 경우는 이것으로 괜찮습니다만, 외부로부터 참조만 하고 싶은 경우는 Getter 를 준비하면 됩니다.

person.es6
const propName = Symbol();
const propAge = Symbol();

/**
 * Person class
 */
class Person {
  /**
   * @constructor
   * @param {string} name
   * @param {number} age
   */
  constructor(name, age) {
    this[propName] = name;
    this[propAge] = age;
  }

  /**
   * @returns {string}
   */
  get name() {
    return this[propName];
  }
}

export default Person;

some.es6
import Person from './person.es6';

const person = new Person('Yamada', 45);

console.log(person.name); // Yamada が出力される

물론 Setter를 준비할 수도 있습니다. 하기의 예라고 건네받은 값을 그대로 세트 하고 있으므로 private 로 하고 있는 의미가 없습니다만, 사실은 값 체크를 사이에 두는 등.

person.es6
const propName = Symbol();
const propAge = Symbol();

/**
 * Person class
 */
class Person {
  /**
   * @constructor
   * @param {string} name
   * @param {number} age
   */
  constructor(name, age) {
    this[propName] = name;
    this[propAge] = age;
  }

  /**
   * @returns {string}
   */
  get name() {
    return this[propName];
  }

  /**
   * @param {string} name
   * @returns {void}
   */
  set name(name) {
    this[propName] = name;
  }
}

export default Person;

덤: private 메소드



생성자내에서 메소드 정의하지 않으면 안 되기 때문에 미묘합니다만.. 만약 그 private 메소드가 인스턴스 변수에 액세스 할 필요가 없는 경우는, 클래스 밖에서 정의하면 좋을지도 모릅니다.
const propName = Symbol();
const propAge = Symbol();
const propSomePrivateMethod = Symbol();

/**
 * Person class
 */
class Person {
  /**
   * @constructor
   * @param {string} name
   * @param {number} age
   */
  constructor(name, age) {
    this[propName] = name;
    this[propAge] = age;
    this[propSomePrivateMethod] = () => {
      console.log(`こんにちは、${this[propName]}さん。`);
    }
  }

  somePublicMethod() {
    // ...

    // private メソッドの呼び出し
    this[propSomePrivateMethod]();
  }
}

export default Person;

그 외 여담


  • 엄밀히 말하면 Symbols private가 아닙니다. 하지만, 거기까지 신경쓰지 않아도 좋을까라는 느낌입니다.

  • WebStorm 등의 IDE를 이용하고 있는 경우는 @private 어노테이션을 붙여 두면, 외부로부터 이용하려고 하면 IDE상에서 경고를 표시해 줍니다.
  • 무리하게 Symbols 를 이용해 번잡해지는 것보다, 현실적으로는 이것으로 충분할지도 모릅니다^^; 메소드에도 @private 어노테이션을 부여할 수 있어요.

  • person.es6
    /**
     * Person class
     */
    class Person {
      /**
       * @constructor
       * @param {string} name
       * @param {number} age
       */
      constructor(name, age) {
        /** @private */
        this.name = name;
        /** @private */
        this.age = age;
      }
    }
    
    export default Person;
    


  • 솔직하게 TypeScript 를 사용하는 것이 좋을지도..
  • 좋은 웹페이지 즐겨찾기