【问题标题】:Extending Builtin Array, super() behaves strangely [duplicate]扩展内置数组,super() 行为异常[重复]
【发布时间】:2018-10-03 15:46:14
【问题描述】:

我正在尝试扩展 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。

【问题讨论】:

    标签: javascript ecmascript-6 es6-class


    【解决方案1】:

    如果我这样做,我将无法使用带有很多参数的扩展运算符,如下所示:

    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));
    

    【讨论】:

    • 啊。我应该意识到RandomArray 也会从Array 继承from 方法。
    猜你喜欢
    • 2015-05-29
    • 2018-07-18
    • 2018-08-18
    • 2015-04-19
    • 1970-01-01
    • 1970-01-01
    • 2010-11-16
    • 2021-12-30
    • 1970-01-01
    相关资源
    最近更新 更多