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:您说过希望某些变量不被删除