扩展内置数组,super()的行为异常

时间:2018-10-03 15:46:15

标签: javascript ecmascript-6 es6-class

我正在尝试扩展JS的本机Array,以便具有实现随机随机播放的数组,如下所示:

 class RandomArray extends Array {

  // Fisher Yates shuffle. Shuffles from the back. 
  // Performs n = size number of shuffles. 
  shuffle(size) {
    size = size || this.length

    if (size > this.length) {
      throw RangeError("Number of shuffles must be fewer than elements in array")
    }

    let curr = this.length, min = this.length - size
    let rand

    while (curr !== min) {
      rand = Math.floor(Math.random() * curr)
      curr -= 1
      this._swap(curr, rand)
    }

    return this
  }

  // in-place swapping of two elements in the array
  // at indices x and y respectively
  _swap(x, y) {
    let tmp = this[x]
    this[x] = this[y]
    this[y] = tmp
  }

但是,如果这样做,我将无法使用带有大量参数的散布运算符,如下所示:

let integers = Array.from({length: 100000}, (d, i) => i))
let ints = new RandomArray(...integers)      // throws RangeError: Maximum call stack size exceeded

因此,我决定尝试将构造函数修改为采用单个列表,而不是通常的可变参数:

class RandomArrayIfAtFirstYouDontSucceed extends Array {
  constructor(lst) {
    super()
    for (let item of lst) super.push(item)
  }

  ...
}

这似乎真的很有效,直到后来这种情况发生:

let integers = Array.from({length: 100000}, (d, i) => i))
let ints = new RandomArrayIfAtFirstYouDontSucceed(integers)  // no more range error, yay!
ints.length         // prints out 100000, yay!
ints.slice(88)      // but now this throws TypeError: lst[Symbol.iterator] is not a function

我认为super()this有点奇怪,并且在某种程度上与迭代器协议有关,但是似乎有很多关于扩展本机的警告。数组,有些我不太了解。有人可以帮忙解释一下吗?

顺便说一句,我正在使用Node v10.11.0和Babel 7.1.2。

1 个答案:

答案 0 :(得分:1)

  

如果执行此操作,则无法使用带有很多参数的spread运算符,如下所示:

let integers = Array.from({length: 100000}, (d, i) => i))
let ints = new RandomArray(...integers)    

是的,您永远无法使用带有大量参数的扩展语法-它们只是不完全适合堆栈。这与您的RandomArray类无关。

只需使用

,而不是修改构造函数以使其与new Array(length)签名合同冲突,只需

let integers = RandomArray.from({length: 10000}, (_, i) => i);
console.log(integers.length);
console.log(integers.slice(0, 88));