在Javascript中实现私有实例变量

Sim*_*lGy 21 javascript private-members

我不知道我多久都错过了这个.我一直假设私有实例变量像这样工作,但他们没有.当然,它们是私有的(如非全局的),但变量是跨实例共享的.这导致了一些非常混乱的错误.

我以为我正在遵循一些最好的图书馆实施的最佳实践,但似乎我错过了一些东西.

var Printer = (function(){
    var _word;

    Printer = function(word){
        _word = word;
    }

    _print = function(){
        console.log(_word);
    }

    Printer.prototype = {
        print: _print
    }
    return Printer;
})();

var a = new Printer("Alex");
var b = new Printer("Bob");

a.print(); //Prints Bob (!)
b.print(); //Prints Bob
Run Code Online (Sandbox Code Playgroud)

我看过这篇文章,但没有描述实现私有实例变量的最佳实践.(这甚至是我想要的名称吗?) JavaScript中私有和实例变量的方法和变量范围

我也查看了这篇文章,但使用'this'关键字是我以前做的.因为它没有混淆我试图避免它.这真的是唯一的方法吗? 在原型继承中实现实例方法/变量

Mat*_*all 28

你正在做那个关闭的一些不稳定的东西._word需要在Printer函数中声明,而不是在匿名封闭的土地上丢失:

function Printer(word) {
    var _word = word;

    this.print = function () {
        console.log(_word);
    }
}

var a = new Printer("Alex");
var b = new Printer("Bob");

a.print(); //Prints Alex
b.print(); //Prints Bob
Run Code Online (Sandbox Code Playgroud)

这保持_word私有,代价是print在每个Printer实例上创建一个新函数.要降低此成本,您需要在原型上公开_word并使用单个print函数:

function Printer(word) {
    this._word = word;
}

Printer.prototype.print = function () {
    console.log(this._word);
}

var a = new Printer("Alex");
var b = new Printer("Bob");

a.print(); //Prints Alex
b.print(); //Prints Bob
Run Code Online (Sandbox Code Playgroud)

它是否真的重要的是_word暴露?就个人而言,我不这么认为,特别是考虑到_前缀.

  • 我认为值得一提的是,OP要求的内容无法真正完成.您给出了一个示例来修复他看到的错误,但代价是将私有成员变量暴露给世界.Javascript不允许公共方法访问私有成员.只有特权方法才能做到这一点,正如您所指出的那样,这些方法会带来内存问题. (9认同)

Ray*_*nos 13

私人是昂贵的,如果可能的话避免它们

私人不存在.你可以做两件事之一来模仿这个.

  • 关闭
  • Weakmaps

关闭

function makePrinter(word) {
  return {
    print: function () {
      console.log(word)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

WeakMap

浏览器对弱映射的支持很糟糕.你可能需要一个仿真,我推荐pd.Name

var Printer = (function () {
  var privates = function (obj) {
    var v = map.get(obj)
    if (v === undefined) {
      v = {}
      map.set(obj, v)
    } 
    return v
  }, map = new WeakMap()

  return {
    constructor: function (word) {
      privates(this).word = word
    },
    print: function () {
      console.log(privates(this).word)
    }
  }
}());
Run Code Online (Sandbox Code Playgroud)

明智的物体

var Printer = {
  constructor: function (word) {
    this._word = word
  },
  print: function () {
    console.log(this._word)
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 我有点困惑.Sensible Objects示例是否仍会在每个Printer实例上创建新的打印功能?在单独的函数中执行Printer.prototype.print不是更好吗? (3认同)

归档时间:

查看次数:

17134 次

最近记录:

7 年 前