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

JavaScript-从Prototype方法访问私有实例变量,javascript,Javascript,[是的,我读过一些类似问题的答案,但没有读到 真的得到了我想要的答案,所以我要问我的问题 无论如何。] 在下面的代码中,我如何将方法setSecret和tellSecret放置在Secret的原型中,同时保持对私有实例变量_Secret的访问,并生成相同的输出 我尝试(参见)将这些方法放置在原型中,但更改了输出 function Secret() { // ===== private ===== var _secret; // ===== public =====

[是的,我读过一些类似问题的答案,但没有读到 真的得到了我想要的答案,所以我要问我的问题 无论如何。]

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

我尝试(参见)将这些方法放置在原型中,但更改了输出

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

这是一个非常丑陋的解决方案,您可能不应该使用它,但它确实有效。基于


这一个与Alon的答案有关,但通过实现WeakMap,不会显示标识索引,也不会累积未使用的对象。虽然在效率方面它是一个更好的解决方案,但在兼容性方面它并不是一个很好的答案。FireFox、Chrome和Node.JS都支持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);

简而言之,不应该在原型方法中使用私有变量。尝试将两者混合需要糟糕的变通方法,而且还有更好的选择。
这里有一个解释。 (这是一个类似答案的摘录:)

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

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

只需对
\u private
字段使用约定即可 因此,我认为使用
\u private
字段最有意义,即使它们仍然是公共的。它使调试更容易,提供了透明度,可以提高性能,这就是我通常使用的方法。
遵守
\u private
字段的约定,一切都会顺利进行。

我只是不明白为什么JS开发人员如此努力地使字段真正私有化

试试这个,告诉我这是不是你要找的。
为了使代码片段更有趣,我在对象机密中添加了两个以上的私有属性
(请注意,您所有的私人VAR都是真正的私人VAR)

函数机密(){
//======私人=======

var\u properties={secret:null,secret2:null,secret3:null}//您不能。JavaScript中没有“私有实例变量”。
\u secret
是一个局部变量,因此只有在构造函数中定义的函数才能访问它。故事结束。可能是“私有实例变量”复制了Felix我的意思是在闭包范围内。请参阅上面的jsbin链接-我可以从原型方法访问_secret,但输出会发生变化,即第二个实例的secret会覆盖第一个实例的secret。我知道你的意思。但这是不可能的,至少在当前的实现中是不可能的。还有几个其他相关问题:,,j是什么ust不可能?请具体说明。您应该提到,
p
的内容不会被自动gc,但内容将保留在内存中,直到页面/应用程序重新加载。“因此,大多数解决方案只是通过方法公开变量,这意味着您正以某种方式公开它。”是的,这些被称为访问器,当您想要控制对变量的访问时(例如,no set、only get或set之前的一些验证逻辑),它们是一个有效的用例。“我只是不明白为什么JS开发人员如此努力地使字段真正私有化。”因为我们不相信其他开发人员不会以非常愚蠢的方式使用我们的变量!
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);