Есть ли способ использовать скрытие информации, не тратя впустую память в прототипах Javascript? - PullRequest
1 голос
/ 20 мая 2019

Я следую Руководству Крокфорда по частным методам в 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 Ответ

3 голосов
/ 20 мая 2019

Если вы не хотите создавать новый 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());
...