覆盖Java的父母获取方法

时间:2019-07-16 18:45:33

标签: javascript arrays inheritance overriding

// 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的大小?

3 个答案:

答案 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}

手段you can't change that property

答案 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是否为数字。我认为它将用于更多内部使用,因此您会照顾好它。