简体   繁体   English

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

[英]In Javascript, How can I have functions for an object that only reside once in memory, while accessing non-static private variables

Consider the following code in java 考虑一下Java中的以下代码

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

x X = new x();
x Y = new x();

Each of X and Y have DoSomethingUsingA(), but the function is only created once in memory. X和Y每个都有DoSomethingUsingA(),但是该函数在内存中仅创建一次。

Now if you try this in javascript 现在,如果您尝试使用javascript

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

var X = new x();
var Y = new y();

DoSomethingUsingA() here is defined twice in memory for each object X & Y. DoSomethingUsingA()在此为每个对象X和Y在内存中定义两次。

Another attempt would be 另一个尝试是

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

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

    return constructor;
}())

var X = new x();
var Y = new y();

now DoSomethingUsingA() is only defined once in memory, but the private variables are static across all derived objects 现在DoSomethingUsingA()在内存中只定义了一次,但是私有变量在所有派生对象中都是静态的

Question: How can I have the functions for all derived objects be defined only once in memory, while having access to non static private variables for each object. 问题:如何让所有派生对象的功能仅在内存中定义一次,同时可以访问每个对象的非静态私有变量。

Consider not trying to hide your private variables so much. 考虑不要试图隐藏太多私有变量。

Despite the fact that in languages like Python or JavaScript you can make some properties invisible for class users using some clever tricks, there are no natural ways or appropriate tools for this in these languages. 尽管在诸如Python或JavaScript之类的语言中,您可以使用一些巧妙的技巧使类用户看不到某些属性,但是在这些语言中,没有自然的方法或合适的工具可以做到这一点。 So if you try to make this sort of constructs, you will end with cumbersome solutions like "static" env object or multiple copies of the same function or something like that. 因此,如果您尝试进行这种构造,您将得到麻烦的解决方案,例如“静态” env对象或同一功能的多个副本或类似的东西。

Quote from the very nice answer to analogous question, fully applicable to JavaScript: 引用类似问题的很好答案 ,完全适用于JavaScript:

It's cultural. 这是文化的。 In Python, you don't write to other classes' instance or class variables. 在Python中,您无需写入其他类的实例或类变量。 In Java, nothing prevents you from doing the same if you really want to - after all, you can always edit the source of the class itself to achieve the same effect. 在Java中,如果您确实想做的话,不会阻止您做同样的事情-毕竟,您始终可以编辑类本身的源代码来实现相同的效果。 Python drops that pretense of security and encourages programmers to be responsible. Python放弃了这种安全性的幌子,并鼓励程序员负责。 In practice, this works very nicely. 实际上,这非常好用。

If instead you decide not to enforce such privacy, there is a couple of tools and conventions that make your "private" vars easy to use: 相反,如果您决定不强制执行此类隐私,则有两种工具和约定使您的“私有”变量易于使用:

  1. Use Object.defineProperty() to control enumerability and configurability of properties. 使用Object.defineProperty()来控制属性的可枚举性和可配置性。

  2. Use underscores in names to prevent names collision in children. 在名称中使用下划线,以防止子名称冲突。 Some libraries have conventions to use other symbols for that. 一些库有约定为此使用其他符号。 For example, AngularJS use $$ prefixes for private variables. 例如,AngularJS对私有变量使用$$前缀。

(And also there is a convention that namesOfParameters start with lower case and ConstructorFunctions - with upper case.) (还有一个约定 ,即namesOfParameters以小写字母开头,而ConstructorFunctions-以大写字母开头。)

So your code will look like this: 因此,您的代码将如下所示:

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";
    // ...
}

How can I have the functions for all derived objects be defined only once in memory, while having access to non static private variables for each object. 如何在内存中只定义一次所有派生对象的功能,同时又可以访问每个对象的非静态私有变量。

You cannot. 你不能。 A "private" variable, ie a local variable from a scope dedicated to an instance, can only be accessed by closure, ie a privileged function which needs to be created in the same scope. “私有”变量(即,专用于实例的作用域中的局部变量)只能通过闭包(即需要在同一作用域中创建的特权函数)进行访问。

Notice that there is nothing wrong with it, functions are cheaper than you seem to think. 请注意,它没有任何问题,功能比您想象的便宜。

One way to make your values referenceable without exposing to each of them directly on your instance is like this 一种使您的值可引用而又不直接在您的实例上公开每个值的方法是这样的

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

Now yes you have a different _getEnvironment function for each instance, but all of the other functions are now shared 现在是的,每个实例都有一个不同的_getEnvironment函数,但是现在共享了所有其他函数

I used an Object env because this is a safe way to look up a value and property look ups are done with a hash table so extremely fast 我用了一个对象 env因为这是查找值和财产的外观以安全的方式UPS与哈希表,所以非常快完成

JavaScript is never really secure, so whilst you can use closures to make it more difficult to access, don't believe that someone motivated wouldn't be able to get around any security measure you try to implement JavaScript从来都不是真正安全的,因此尽管您可以使用闭包使其更难以访问,但不要相信有动机的人将无法解决您尝试实施的任何安全措施

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM