如何创建共享,特权,公共方法?

时间:2014-05-15 01:07:37

标签: javascript node.js ecmascript-5

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

但是,我想避免的是每次创建新特权方法的内存和性能开销。所以我想分享它们。

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

请求示例:

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

这有效,我有一个可以访问私有变量“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

这与“成长”方法相同,但现在年龄是公开的。

3 个答案:

答案 0 :(得分:1)

你可以做这样的事情(没有ES6),虽然我认为这不是一个好的解决方案。

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

on jsFiddle

由@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

答案 1 :(得分:1)

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

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);
    }
}());

我们使用functional red black treesO(log n)时间内有效地插入,删除和获取对象的私有属性。因此,例如,假设您一次创建Person的2251799813685248个实例。它仍然只需要51个操作来插入,删除和从树中获取对象。

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

var dan = new Person(10);
dan.grow();
dan.age;                  // undefined
dan.destroy();            // frees shared memory

但是我不推荐这种方法,因为:

  1. 这不必要地使事情变得复杂。
  2. 如果您忘记拨打destroy,那么您将浪费大量内存。
  3. 每个“特权”功能都有额外的开销。
  4. secret对象所做的更改不会反映在私有变量上。
  5. 相反,我建议您只使用公共属性。完全没有理由使用私有财产。你害怕什么?


    修改:如果你想要的是阻止私人财产通过console.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。简而言之,你将获得两全其美。

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

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

答案 2 :(得分:0)

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