Javascript 如何创建共享的、特权的、公共的方法?

Javascript 如何创建共享的、特权的、公共的方法?,javascript,node.js,ecmascript-5,Javascript,Node.js,Ecmascript 5,我的一个类的一些方法现在是公共的,但是可以访问私有变量(它们是特权的)。这是因为它们是在类构造函数中创建的,所以它们的闭包可以访问对象闭包 不过,我想避免的是每次创建新的特权方法时的内存和性能开销。所以我想和大家分享 有没有办法将特权方法放入原型中 要求举例说明: function Person(age) { // age is private this.grow = function() { // grow is now public, but can access pri

我的一个类的一些方法现在是公共的,但是可以访问私有变量(它们是特权的)。这是因为它们是在类构造函数中创建的,所以它们的闭包可以访问对象闭包

不过,我想避免的是每次创建新的特权方法时的内存和性能开销。所以我想和大家分享

有没有办法将特权方法放入原型中

要求举例说明:

function Person(age) {       // age is private
    this.grow = function() { // grow is now public, but can access private "age"
        age += 1;
    }
}

dan = new Person(10);
dan.grow();
dan.age;                    // undefined
这是可行的,我有一个公共方法“grow”,可以访问私有变量“age”,但必须为每个对象重新创建grow

更有效的方法是:

function Person(age) { // age is private
    this.age = age;    // but this.age is public
}
Person.prototype.grow = function() {
    this.age += 1;
}

dan = new Person(10);
dan.grow();
dan.age;              // 11

<>这是“增长”的方法,但现在的年龄是公开的。

你可以做这样的事情(没有ES6),虽然我不认为这是一个好的解决方案。< /P>
var Person = (function () {
    var id = 0,
        data = {},
        key = Math.random();

    function Person(age) {
        var thisId = id;

        data[id] = age;
        id += 1;

        this.getId = function(check) {
            if (check !== key) {
                return undefined;
            }

            return thisId;
        };
    }

    Person.prototype.grow = function () {
        var thisId = this.getId(key);

        data[thisId] += 1;
        console.log(data[thisId]);

        return this;
    };

    Person.prototype.destroy = function () {
        var thisId = this.getId(key);

        data[thisId] = null;
        delete data[thisId];
    };

    return Person;
}());

var dan = new Person(10);

dan.grow();
console.log(dan.age); // undefined
console.log(dan.getId()); // undefined

由@DanRedux添加:

function Person(age) {
 this.private = {age:age}; }
Person.prototype.grow = function() {
  this.private.age += 1; }

dan = new Person(10);
dan.grow();
dan.age; // undefined
dan.private.age; // 11

正如您所说,特权方法是通过将它们放在构造函数范围中创建的。根据该定义,它们不能在实例之间共享;否则他们将无法访问特定于实例的作用域。

是的,这确实是可能的。然而,这需要一些技巧:

var createTree = require("functional-red-black-tree");

var Person = (function () {
    var tree = createTree(), id = 0;

    return function (age) {
        tree.insert(id, {
            age: age
        });

        this.id = id++;

        this.grow = grow;

        this.destroy = destroy;
    };

    function grow() {
        tree.get(this.id).age++;
    }

    function destroy() {
        tree.remove(this.id);
    }
}());
我们使用在
O(logn)
时间内高效地插入、删除和获取对象的私有属性。因此,例如,假设您一次创建2251799813685248个
Person
实例。它仍然只需要51个操作就可以插入、删除和从树中获取对象

您可以按如下方式使用它:

var dan = new Person(10);
dan.grow();
dan.age;                  // undefined
dan.destroy();            // frees shared memory
但是,我不推荐这种方法,因为:

  • 它不必要地使事情复杂化
  • 如果忘记调用
    destroy
    ,则会浪费大量内存
  • 每个“特权”函数都有额外的开销
  • secret
    对象所做的更改不会反映在私有变量上
  • 相反,我建议您对所有内容都使用公共属性。根本没有理由使用私有财产。你害怕什么


    编辑:如果您只想防止通过
    控制台.log打印出您的私有属性,则可以将其设置为不可枚举:

    function Person(age) {
        Object.defineProperty(this, "age", {
            enumerable: false,
            writable: true,
            value: age
        });
    }
    
    Person.prototype.grow = function () {
        this.age++;
    };
    
    现在,
    age
    属性(尽管是公共的)将不会出现在
    for in
    循环中或通过
    console.log
    显示。简言之,你可以两全其美

    正如我在评论中所说,绝对没有必要使用共享特权方法黑客。只需将所有变量公开且不可枚举即可


    此外,在它们前面加一个下划线,表示它们不应被篡改。所有优秀的JavaScript程序员都使用这种约定。

    这是问“我可以在原型定义的类中使用私有变量吗”的聪明方法吗?不太可能,但是构造函数可以访问外部世界看不到的“对象存储”,而无需在每次调用构造函数时生成闭包。您是否遇到了使闭包不可用的性能问题?我在使用您的行话(在javascript上下文中)时遇到了问题,您能否添加一个您正在尝试重构的示例?添加的示例@GitaarLAB Oh,spender,这实际上看起来是一个很好的解决方案,但guid现在必须公开。。。所以这是一个99%的解决方案(比我现在拥有的更好)。很好的例子(很好的问题),至少它可以防止XY问题!所以,实际上你希望年龄是私人的?为什么它实际上必须是私人的,而不仅仅是按惯例是私人的?典型的做法是在私有变量前面加上一个
    。我们实际上可以这样做:
    this.privates={}
    ,然后将所有私有变量放在那里。这样就没有“id”逻辑,只有一个公共变量,它得到GC'd。但是,它仍然不是完美的,因为它仍然公开了一个变量。确切地说,我以为你不想公开数据?这只公开了一个id。但是你刚才添加到我的答案中的内容现在公开了数据。哦,我明白了。我明白你想说的,数据不再在对象内部。有趣的解决方案。当然,您仍然可以通过执行
    数据[dan.getId()]
    ,甚至只是打印
    数据
    数组来获得它。看起来甚至
    数据
    都可以隐藏在类中(有点像静态文件)。现在如果我们能隐藏getId就好了。有趣的想法。。把这段代码放在闭包里怎么样<代码>var Person=(函数(){/*代码段Xotic750 here*/return Person;})()希望你能明白。这样,Person与
    数据处于同一个私有范围内。另外,在大多数引擎上,将
    data[id]
    设置为
    null
    delete
    更好。我不喜欢在执行console.log时出现隐私。然而,我也希望保护某些变量不被更改。这当然不能回答“有没有办法将特权方法放入原型中?”的问题,但它确实导致了通过执行
    键.push(这个)来消除
    getId
    需要的可能性
    但是由于使用数组和ES5方法(可以填充)的需要,减少了可用的REORD数或REORD数。为了让未来的读者在Google上搜索一夜,此语句:
    但是由于使用数组,减少了可用的记录数或REORD数。
    。该规范规定,“实”数组索引(在javascript方法中)必须是正整数,必须通过(引擎内部)“u32int”函数传递。因此,“实”数组索引限制为32位(无符号)=
    2^32-1
    =
    429467295(dec)
    。但是,任何超出此范围的内容都将成为数组的属性(使用“类似数组”的界面
    []
    ),除非
    取消移位
    /
    推送
    等。在这种情况下,它将失败。@DanRedux:您说过希望某些变量不被删除