我的一个类的一些方法现在是公共的,但可以访问私有变量(它们是特权的)。这是因为它们是在类构造函数中创建的,因此它们的闭包可以访问对象闭包。
但是,我想避免的是每次创建新特权方法的内存和性能开销。所以我想分享它们。
有没有办法将特权方法放入原型?
请求示例:
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
这与“成长”方法相同,但现在年龄是公开的。
答案 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 trees在O(log n)
时间内有效地插入,删除和获取对象的私有属性。因此,例如,假设您一次创建Person
的2251799813685248个实例。它仍然只需要51个操作来插入,删除和从树中获取对象。
您可以按如下方式使用它:
var dan = new Person(10);
dan.grow();
dan.age; // undefined
dan.destroy(); // frees shared memory
但是我不推荐这种方法,因为:
destroy
,那么您将浪费大量内存。secret
对象所做的更改不会反映在私有变量上。相反,我建议您只使用公共属性。完全没有理由使用私有财产。你害怕什么?
修改:如果你想要的是阻止私人财产通过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)
好吧,正如您所说,特权方法是通过将它们放在构造函数范围中来创建的。根据该定义,他们不能在实例之间共享;否则他们将无法访问特定于实例的范围。