// Garbage collection friendly list.
class GCFList extends Array {
size;
constructor(initSize = 0) {
super(initSize);
this.size = initSize;
}
push(content){
this[this.size] = content;
this.size++;
}
pop(){
this.size--;
let returnContent = this[this.size];
this[this.size] = null;
return returnContent;
}
get length(){
return this.size;
}
set length(newLength){
}
}
var l = new GCFList();
l.push(2);
l.pop();
console.log(l.length);
console.log("Expecting 0, but getting 1");
我正在创建一个垃圾回收友好数组列表。我想将其用作普通数组。当我尝试覆盖length getter方法时,似乎仍在访问父级(数组)长度。调用l.length时如何获得l的大小?
答案 0 :(得分:4)
您不能覆盖数组的.length
行为。它不是一个getter / setter(即使它的行为类似),也不是从Array.prototype
继承的。每个数组实例都有其自己的.length
数据属性,这使您在GCFList.prototype
上的getter / setter蒙上阴影。
答案 1 :(得分:2)
除了您实际上无法比JS Array效率更高(它们稀疏等)之外,还扩展了Array,并且数组的length
属性不可配置:
Object.getOwnPropertyDescriptor(l, 'length')
// {value: 1, writable: true, enumerable: false, configurable: false}
答案 2 :(得分:0)
(以下解决方案与问题间接相关,但同时又太长,无法发表评论。)
如您所见,扩展Array可能会出现问题。这可能是JavaScript所能提供的最好的集合,但它本身就可以。我想建议的是以下内容:
(是的,我相信您要在问题中查找的结构是堆栈。)
class Stack {
constructor(size) {
this.size = size;
this.head = -1;
this.stack = Array.from({ length: size }, () => undefined);
}
push(item) {
if (this.head + 1 == this.size) {
// if you prefer, this might silently fail but I chose to be explicit
throw new Error('Stack full!');
}
this.head += 1;
this.stack[this.head] = value;
return this; // so it can be chained and `this.push(1).push(2)` will be possible
}
pop() {
if (this.head == -1) {
// if you prefer, this might silently fail but I chose to be explicit
throw new Error('Stack empty!');
}
const popped = this.stack[this.head];
// this is theoretically optional but in case of objects we’ll get rid of reference,
// hence allowing for garbage collection
this.stack[this.head] = undefined;
this.head -= 1;
return popped;
}
get length() {
// I put this here as it was in your example
// but either having `lenght` property or reading from `string` is actually enough
return this.size;
}
set length(size) {
if (size > this.size) {
for (let i = this.size; i < size; i++) {
this.stack.push(undefined);
}
} else if (size < this.size) {
if (this.head > size) {
this.head = size - 1; // set it at the end of shorter stack if head would be oustide
}
for (let i = this.size; i > size; i--) {
this.stack.pop();
}
}
}
}
这为您提供了一个固定长度的“数组”,如果您尝试扩展它,它将失败。我读过某个地方,对于不改变长度的游戏数组来说,效果更好。无论如何,您已经进行了分析。另外,由于这个原因,我不建议使用不可变的结构,因为这会占用更多内存。
您可能还需要使用peek
这种可能的方法,该方法允许查看当前值而不弹出它。
这是我刚刚写的概念证明,因此如果您决定使用它,可能需要进行一些调整,但这就是我的想法。
因为这意味着要快,所以我放弃了一些过于防御的措施,例如检查发送给构造函数的size
是否为数字。我认为它将用于更多内部使用,因此您会照顾好它。