gpt4 book ai didi

javascript - 使匿名函数中包含的原型(prototype)方法可以访问私有(private)实例变量

转载 作者:行者123 更新时间:2023-11-30 12:35:31 25 4
gpt4 key购买 nike

背景

我决定通过用 JS 制作一个简单的计算器应用来练习。第一步是实现堆栈类。然而,在使用揭示原型(prototype)模式 (?) 实现数据封装时,我遇到了一些问题。这是它现在的样子:

堆栈“类”:

var Stack = (function () { 

var Stack = function() {
this.arr = []; // accessible to prototype methods but also to public
};

Stack.prototype = Object.prototype; // inherits from Object

Stack.prototype.push = function(x) {
this.arr.push(x);
};

Stack.prototype.pop = function() {
return this.arr.length ? (this.arr.splice(this.arr.length - 1, 1))[0] : null;
};

Stack.prototype.size = function() {
return this.arr.length;
};

Stack.prototype.empty = function() {
return this.arr.length === 0;
};

return Stack;

})();

测试代码:

var s1 = new Stack();
var s2 = new Stack();

for(var j = 1, k = 2; j < 10, k < 11; j++, k++) {

s1.push(3*j);
s2.push(4*k);

}

console.log("s1:");
while(!s1.empty()) console.log(s1.pop());
console.log("s2:");
while(!s2.empty()) console.log(s2.pop());

问题

唯一的问题是 arr 是可访问的。我想以某种方式隐藏 arr 变量。

尝试解决方案

我的第一个想法是让它成为一个像Stack这样的私有(private)变量:

var Stack = (function () {

var arr = []; // private, but shared by all instances

var Stack = function() { };
Stack.prototype = Object.prototype;

Stack.prototype.push = function(x) {
arr.push(x);
};

// etc.

})();

当然,这种方法行不通,因为 arr 变量会被每个实例共享。所以这是创建私有(private) class 变量的好方法,但不是私有(private)实例变量。

我想到的第二种方法(这真的很疯狂而且绝对不利于可读性)是使用随机数来限制对数组变量的访问,几乎就像密码一样:

var Stack = (function() {

var pass = String(Math.floor(Math.pow(10, 15 * Math.random()));
var arrKey = "arr" + pass;

var Stack = function() {
this[arrKey] = []; // private instance and accessible to prototypes, but too dirty
};

Stack.prototype = Object.prototype;

Stack.prototype.push = function(x) {
this[arrKey].push(x);
};

// etc.

})();

这个解决方案……很有趣。但显然不是我想做的。

最后一个思路,也就是什么Crockford does , 允许我创建一个私有(private)实例成员,但我无法告诉它让我定义的公共(public)原型(prototype)方法可见。

var Stack = (function() {

var Stack = function() {
var arr = []; // private instance member but not accessible to public methods
this.push = function(x) { arr.push(x); }; // see note [1]
}

})();

[1] 这几乎就在那里,但我不想在 var Stack = function() {...} 中有函数定义,因为它们每次都会重新创建创建一个实例。聪明的 JS 编译器会意识到它们不依赖于任何条件并缓存函数代码,而不是一遍又一遍地重新创建 this.push,但如果可以的话,我宁愿不依赖推测性缓存避免它。

问题

有没有办法创建原型(prototype)方法可以访问的私有(private)实例成员?通过某种方式利用由封闭的匿名函数创建的“影响力泡沫”?

最佳答案

您可以使用为您创建实例的工厂函数:

function createStack() {
var arr = [];

function Stack() {

};

Stack.prototype = Object.prototype; // inherits from Object

Stack.prototype.push = function(x) {
arr.push(x);
};

Stack.prototype.pop = function() {
return arr.length ? (this.arr.splice(this.arr.length - 1, 1))[0] : null;
};

Stack.prototype.size = function() {
return arr.length;
};

Stack.prototype.empty = function() {
return arr.length === 0;
};

return new Stack();

}

您将在每次执行工厂函数时定义类,但您可以通过更改它以在构造函数之外定义大部分 Stack 来解决这个问题,例如不使用 arr 的部分可以在原型(prototype)链的更上游。我个人现在使用 Object.create 而不是原型(prototype),而且我几乎总是使用工厂函数来创建这些类型的对象的实例。

您可以做的另一件事是维护一个计数器,用于跟踪实例并保留数组数组。

var Stack = (function() {

var data = [];


var Stack = function() {
this.id = data.length;
data[this.id] = [];
};

Stack.prototype = Object.prototype;

Stack.prototype.push = function(x) {
data[this.id].push(x);
};

// etc.

}());

现在你有了隐藏数据多维数组,每个实例只在该数组中维护它的索引。不过,您现在必须小心管理内存,以便在不再使用您的实例时删除该数组中的内容。除非您小心处理数据,否则我不建议这样做。

关于javascript - 使匿名函数中包含的原型(prototype)方法可以访问私有(private)实例变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26194707/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com