JavaScript - 从Prototype方法访问私有实例变量

时间:2014-02-03 06:28:05

标签: javascript

  

[是的,我已经阅读了类似问题的几个答案,但没有   真的得到我正在寻找的答案,所以我要问我的问题   反正。]

在下面的代码中,如何将方法setSecret和tellSecret放在Secret的原型中,同时仍然保持对私有实例变量_secret的访问,并产生相同的输出?

我尝试this(请参阅jsbin)将方法放在原型中,但更改了输出。

function Secret() {

    // ===== private =====

    var _secret;

    // ===== public =====

    this.setSecret = function (secret) {
        _secret = secret;
    };

    this.tellSecret = function () {
        console.log(_secret);
    };
}

var secretA = new Secret();
var secretB = new Secret();

secretA.setSecret("AAA");
secretB.setSecret("BBB");

setTimeout(function () {
    console.log("Secret A");
    secretA.tellSecret();

    console.log("Secret B");
    secretB.tellSecret();
}, 1000);


// ===== output =====

Secret A
AAA
Secret B
BBB

4 个答案:

答案 0 :(得分:6)

简而言之,不应该使用原型方法的私有变量。尝试混合两者需要糟糕的解决方法,并且有更好的选择 这是解释原因。 (这是类似答案的摘录:https://stackoverflow.com/a/21522742/272072

原型方法

在JavaScript中,原型方法允许多个实例共享原型方法,而不是每个实例都有自己的方法 缺点是this是每次调用原型方法时唯一的不同之处。
因此,任何"私人"必须通过this访问字段,这意味着它们也必须可公开访问。因此,我们所能做的最好的事情就是坚持_private字段的命名约定。

与私有变量混合

当您使用闭包创建私有变量时,您无法从原型方法访问它,除非通过this变量公开。因此,大多数解决方案只是通过方法公开变量,这意味着您以某种方式公开公开它。

只需使用_private字段

的约定

所以,我认为使用_private字段最有意义,即使它们仍然是公开的。它使调试更容易,提供透明度,可以提高性能,以及我通常使用的内容 坚持_private领域的惯例,一切都很顺利 我只是不明白为什么JS开发人员努力使字段真正私有化。

答案 1 :(得分:1)

这个与Alon的答案有关,但是通过实现WeakMap,不会显示识别索引,也不会累积未使用的对象。虽然在效率方面是一个更好的解决方案,但在兼容性方面却不是一个好的答案。 FireFox,Chrome和Node.JS支持WeakMaps,所以我觉得值得一提。

请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap了解详情。

var Secret = (function(){

   var secrets=new WeakMap();

  function Secret() {

    // ===== private =====

    secrets.set(this, null);

   // ===== public =====

   }

    Secret.prototype.setSecret = function (secret) {
       secrets.set(this, secret);
    };

    Secret.prototype.tellSecret = function () {
        console.log(secrets.get(this));
    };


   return Secret;

}());


var secretA = new Secret();
var secretB = new Secret();

secretA.setSecret("AAA");
secretB.setSecret("BBB");

setTimeout(function () {
    console.log("Secret A", secretA  );
    secretA.tellSecret();

    console.log("Secret B", secretB );
    secretB.tellSecret();
}, 1000);

答案 2 :(得分:0)

这是一个令人难以置信的难看的解决方案,你可能不应该使用它,但它的工作原理。基于this answer

var Secret = (function () {
    var instance = 0,
        p = [];

    function Secret() {
        this.i = instance++;
        p[this.i] = {};
        p[this.i]._secret = null;
    }

    Secret.prototype.setSecret = function (secret) {
        p[this.i]._secret = secret;
    };

    Secret.prototype.tellSecret = function () {
        console.log(p[this.i]._secret);
    };

    return Secret;
})();

var secret = new Secret();
secret.setSecret("A");

var secret2 = new Secret();
secret2.setSecret("B");

console.log(secret._secret)  // => undefined

secret.tellSecret()          // => A
secret2.tellSecret()         // => B

答案 3 :(得分:0)

试试这个,并告诉我这是你搜索的内容 为了使这个片段更有趣,我向你的对象添加了2个私有属性 (请注意,您的所有私人变量都是私有的)

Error creating foreign key on SectionNumber (check data types)