Есть ли способ использовать скрытие информации, не тратя впустую память в прототипах Javascript?

Я следую руководству Крокфорда по частным методам в Javascript и борюсь с чем-то. Я пытаюсь оптимизировать этот код

function Container(param) {

    function dec() {
        if (secret > 0) {
            secret -= 1;
            return true;
        } else {
            return false;
        }
    }

    this.member = param;
    var secret = 3;
    var that = this;

    this.service = function () {
        return dec() ? that.member : null;
    };
}

путем определения функций вне конструктора, чтобы новый объект функции не создавался при каждом создании нового экземпляра.

Я до сих пор не знаю, как это сделать для тех, кого он называет частными (любая помощь приветствуется). Для тех, кого он называет привилегированными методами, это то, что я пытаюсь сделать:

function Container(param) {

    function dec() {
        if (secret > 0) {
            secret -= 1;
            return true;
        } else {
            return false;
        }
    }

    this.member = param;
    var secret = 3;
    var that = this;
}
Container.prototype.service = function() {
    return dec() ? that.member : null; 
};

но если я проверю это так

d1 = new Container("content");
d1.service();

Я получаю эту ошибку:

ReferenceError: dec is not defined

Означает ли это, что нельзя использовать преимущества закрытых / привилегированных методов, которые использует Крокфорд И оптимизировать использование памяти, связывая все экземпляры класса с одним и тем же функциональным объектом? Я надеюсь, что вы докажете, что я неправ.

1 ответ

Решение

Если вы не хотите создавать новый dec на каждый звонок Container, ты можешь сделать Container в IIFE - определить dec когда Container определяется, а затем вернуть фактический Container конструктор из IIFE, так что dec можно ссылаться только изнутри Container, Инкапсулировать secrets, использовать Map индексируется экземпляром вместо использования простого var secrets в конструкторе, так что (общий) dec а также service функции могут видеть и использовать карту.

На самом деле, как отмечается в комментариях, вероятно, было бы лучше использовать WeakMap, чтобы связанный с экземпляром секрет можно было собирать мусором после того, как экземпляр GC'd:

const Container = (() => {
  const secretsByInstance = new WeakMap();
  function dec(instance) {
    const secret = secretsByInstance.get(instance);
    if (secret > 0) {
      secretsByInstance.set(instance, secret - 1);
      return true;
    } else {
      return false;
    }
  }
  function Container(param) {
    secretsByInstance.set(this, 3);
    this.member = param;
  }
  Container.prototype.service = function() {
   return dec(this) ? this.member : null;
  };
  return Container;
})();

d1 = new Container("content");
console.log(d1.service());
console.log(d1.service());
console.log(d1.service());
console.log(d1.service());

Другие вопросы по тегам