1

我正在关注Crockford 的 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

这是否意味着无法利用 Crockford 使用的私有/特权方法的优势并通过将类的所有实例链接到同一个函数对象来优化内存使用?我希望你能证明我是错的。

4

1 回答 1

3

如果您不想dec在每次调用时都创建一个 new Container,您可以将Container其设置为 IIFE - 定义dec何时Container定义,然后Container从 IIFE 返回实际的构造函数,这样dec只能从Container. 要封装secrets,请在构造函数Map中使用按实例索引的索引,而不是使用普通var secrets的,以便(共享)decservice函数可以看到和使用 Map。

实际上,正如评论所指出的,使用 Wea​​kMap 可能会更好,这样一旦实例被 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());

于 2019-05-20T00:39:40.827 回答