在Javascript中,当访问非静态私有变量时,如何使对象的函数只驻留在内存中一次

在Javascript中,当访问非静态私有变量时,如何使对象的函数只驻留在内存中一次,javascript,function,design-patterns,constructor,private-members,Javascript,Function,Design Patterns,Constructor,Private Members,考虑以下java代码 class x { private boolean a; public void DoSomethingUsingA() { ....... // "a" referenced here } } x X = new x(); x Y = new x(); X和Y都有DoSomethingUsingA(),但该函数在内存中只创建一次 现在,如果您在javascript中尝试这一点 function x() { var a;

考虑以下java代码

class x {
   private boolean a;
   public void DoSomethingUsingA() {
       ....... // "a" referenced here
   }
}

x X = new x();
x Y = new x();
X和Y都有DoSomethingUsingA(),但该函数在内存中只创建一次

现在,如果您在javascript中尝试这一点

function x() {
    var a;
    this.DoSomethingUsingA= function() {
        ........ // "a" referenced here
    }
}

var X = new x();
var Y = new y();
这里的DoSomethingUsingA()在内存中为每个对象X和Y定义了两次

另一种尝试是

var x = (function() {
    var a;
    function constructor() {
      ........
    }

    constructor.prototype.DoSomethingUsingA = function() {
       ....... // "a" referenced here
    }

    return constructor;
}())

var X = new x();
var Y = new y();
现在DoSomethingUsingA()在内存中只定义一次,但是私有变量在所有派生对象中都是静态的

问题:
如何让所有派生对象的函数在内存中只定义一次,同时访问每个对象的非静态私有变量。

一种方法可以使值可引用,而无需在实例上直接暴露给每个值

function Foo(b) {
    var env = {}; // Object to hold variables
    this._getEnvironment = function () { // might want to make this non-enumerable
        return env;
    };
    env.bar = b; // example
}
Foo.prototype.getBar = function () { // inherited, shared
    var env = this._getEnvironment();
    return env['bar'];
};

var x = new Foo(1),
    y = new Foo(2);
x.getBar(); // 1
y.getBar(); // 2
// but remember
x._getEnvironment()['bar']; // 1, still reachable
现在是的,每个实例都有一个不同的
\u getEnvironment
函数,但所有其他函数现在都是共享的

我使用了一个Object
env
,因为这是一种安全的查找值的方法,而属性查找是使用哈希表完成的,速度非常快

JavaScript从来都不是真正安全的,所以虽然您可以使用闭包使其更难访问,但不要相信有人会绕过您尝试实现的任何安全措施

如何让所有派生对象的函数在内存中只定义一次,同时访问每个对象的非静态私有变量

你不能。“私有”变量,即专用于实例的作用域中的局部变量,只能通过闭包访问,即需要在同一作用域中创建的特权函数


请注意,它没有什么问题,函数比您想象的要便宜。

考虑不要试图隐藏您的私有变量太多

尽管在Python或JavaScript等语言中,您可以使用一些巧妙的技巧使某些属性对类用户不可见,但在这些语言中,没有自然的方法或合适的工具来实现这一点。因此,如果您尝试进行这种构造,您将以诸如“静态”env对象或同一函数的多个副本之类的麻烦解决方案结束

引用到类似问题,完全适用于JavaScript:

这是文化。在Python中,您不会写入其他类的实例或类变量。在Java中,如果您真的想这样做,没有什么可以阻止您这样做——毕竟,您可以随时编辑类本身的源代码以达到相同的效果。Python放弃了安全性的伪装,鼓励程序员负责任。实际上,这非常有效

如果您决定不强制执行此类隐私,则有两种工具和约定可以使您的“私有”VAR易于使用:

  • 用于控制属性的可枚举性和可配置性

  • 在名称中使用下划线可防止子级中的名称冲突。有些库有使用其他符号的约定。例如,AngularJS使用$$前缀作为私有变量

  • (还有一种方法是参数的名称以小写开头,构造函数的函数以大写开头。)

    因此,您的代码将如下所示:

    function X() {
        // constructor
    }
    
    Object.defineProperty(X.prototype, "__a", {
        "writable": true,
        "value":    null
        // "configurable" and "enumerable" are false by default
    });
    
    X.prototype.doSomethingUsingA = function() {
        this.__a = "somevalue";
        // ...
    }
    

    JavaScript没有一个“私有的”和“公共的”,为了访问这样的东西,你需要使它的引用环境可能是一个坏的名字选择,你可能想考虑调用它,例如GestStaseCavaRabeLeEMS,我在这个问题中有一些歧义(以GET…()为例)。我现在已经修好了。它不是关于引用和返回私有变量,而是关于在函数中使用它们。此外,“getEnvironmentVariable”将在中创建两次memory@man我说过每个实例将获得一个新的
    gEnv
    ,区别在于所有其他函数都可以通过
    gEnv
    ,因此不需要有新实例themselves@man您试图解决的问题假设存在“私有”和“公共”两种情况,在JavaScript中,这些概念根本不存在。您可以使用作用域和闭包来创建类似的内容,但它与具有该功能的语言不同。也许你应该考虑一下为什么你想要一些私人的东西,如果不是这样,那真的重要吗?“编辑”是Crockford对该主题的理解。请将其设置为公共属性,可能带有下划线前缀。您的
    getEnvironmentVariable
    不安全,假装安全。此外,你还需要一些类似于getter的东西——将一切都复杂化。