在Javascript中实现私有实例变量

在Javascript中实现私有实例变量,javascript,private-members,Javascript,Private Members,我不知道我怎么会错过这么长时间。我一直假设私有实例变量是这样工作的,但它们不是。当然,它们是私有的(就像在非全局中一样),但变量是跨实例共享的。这导致了一些非常混乱的错误 我以为我在遵循一些最好的库所实施的最佳实践,但似乎我遗漏了一些东西 var Printer = (function(){ var _word; Printer = function(word){ _word = word; } _print = function(){

我不知道我怎么会错过这么长时间。我一直假设私有实例变量是这样工作的,但它们不是。当然,它们是私有的(就像在非全局中一样),但变量是跨实例共享的。这导致了一些非常混乱的错误

我以为我在遵循一些最好的库所实施的最佳实践,但似乎我遗漏了一些东西

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
我看过这篇文章,但它没有描述实现私有实例变量的最佳实践。(这是我想要的名字吗?)

我也看了这篇文章,但使用“this”关键字是我过去常做的事。因为它不会让我困惑,所以我试图避免它。这真的是唯一的办法吗?

你在做一些不可靠的事情<代码>\u word需要在
打印机
功能中声明,不能在匿名关闭栏中丢失:

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
这将保持word的私有性,代价是在每个
打印机
实例上创建一个新的
打印
函数。为了降低成本,您需要公开word,并在原型上使用单个打印功能:

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
\u word
被暴露真的很重要吗?就我个人而言,我不这么认为,尤其是考虑到前缀

隐私是不存在的。您可以做以下两件事之一来模拟这一点

  • 闭包
  • 懦夫
闭包 懦夫 对浏览器的支持非常糟糕。我建议,您可能需要进行模拟

敏感物体
使用
对代码进行轻微修改即可。未为
a
对象实例化
Printer.prototype.print
的正确实例

var Printer = (function(){
    var _word;

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

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

    Printer.prototype = {
        print: _print
    }

    return Printer;
})();

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

a.print(); //Prints Alex
b.print(); //Prints Bob

如果您愿意使用ES2015课程(我已经回答了,但为了方便起见,请重复)

使用ESNext,您可以这样使用:

class Foo {
  #bar = '';
  constructor(val){
      this.#bar = val;
  }
  otherFn(){
      console.log(this.#bar);
  }
}

私有字段#bar在Foo类之外是不可访问的。

我明白了,所以我们作为JavaScript开发人员达成了一项协议,不修改以“#”开头的对象的属性?如果每个人都这么做,我认为效果相当不错。它确实需要在我需要变量的任何地方使用“this.\u word”,但也许我是一个混淆的纳粹分子。我认为值得一提的是,OP要求的东西实际上无法实现。您给出了一个示例,该示例修复了他看到的bug,但代价是向世界公开私有成员变量。Javascript不允许公共方法访问私有成员。只有特权方法才能做到这一点,正如您所注意到的,这些方法会带来内存问题。1:天哪,我不知道有可能这么擅长JS。干得好,雷诺斯。他说:懦夫看起来一团糟,我不想和他们有任何关系。3:您所描述的可感知对象为我提供了按照_约定是私有的实例变量。这和马特·鲍尔建议的解决方案是一样的,所以这一定是正确的方向。我有点困惑。Sensible Objects示例是否仍会在每个打印机实例上创建新的打印函数?在一个单独的函数中执行Printer.prototype.print不是更好吗?4年后,我写了一篇关于实现这一点的博客文章:现在处于第3阶段,并且以TypeScript 3.8发布。
var Printer = {
  constructor: function (word) {
    this._word = word
  },
  print: function () {
    console.log(this._word)
  }
}
var Printer = (function(){
    var _word;

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

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

    Printer.prototype = {
        print: _print
    }

    return Printer;
})();

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

a.print(); //Prints Alex
b.print(); //Prints Bob
class Foo {
  #bar = '';
  constructor(val){
      this.#bar = val;
  }
  otherFn(){
      console.log(this.#bar);
  }
}