1

Let assume we got following class:

class Content extends Array {
  delete (index) {
    return [...this.slice(0, index), ...this.slice(index + 1)]
  }

  copy () {
    // Create a copy!
  }
}

const content = new Content('alpha', 'beta', 'gamma')
const copy = content.copy()
console.log(copy.delete(1)) // ["alpha", "gamma"]

How can we create a copy of an instance of this class?

  • Welcome to Stack Overflow! Please read through the [help], in particular [*How do I ask a good question?*](/help/how-to-ask) Your best bet here is to do your research, [search](/help/searching) for related topics on SO, and give it a go. ***If*** you get stuck and can't get unstuck after doing more research and searching, post a [mcve] of your attempt and say specifically where you're stuck. People will be glad to help. – T.J. Crowder Sep 21 '20 at 17:22
  • @T.J.Crowder Not quite sure why you posted that. It's a fairly simple question. Maybe look for a duplicate? – Robert Harvey Sep 21 '20 at 17:23
  • @RobertHarvey - Because the question doesn't show any attempt to solve the problem it presents, which (as I understand it) is expected, even nowadays. (I'm not trying to make new rules; I'm trying to follow the rules that the site has.) Copying an array subclass is *slightly* different from copying an array (although because Array's methods are fairly smart, most of the ways you do it just...work). – T.J. Crowder Sep 21 '20 at 17:28

2 Answers2

1

.slice can shallow-copy an array. Luckily, the new instance that .slice creates will be an instance of the subclass automatically; there's no need to do anything else manually, it'll automatically return a Content instance:

class Content extends Array {
  delete (index) {
    return [...this.slice(0, index), ...this.slice(index + 1)]
  }

  copy () {
    return this.slice();
  }
}

const content = new Content('alpha', 'beta', 'gamma')
const copy = content.copy()
console.log(copy.delete(1)) // ["alpha", "gamma"]

As the specification says, the new array-like object created, A, is created by:

  1. Let A be ? ArraySpeciesCreate(O, count).

where O is the original array-like object being sliced. That's why someArraySubclass.slice() will return an object which is an instance of SomeArraySubclass.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
0

You can use ...this inside your class to access the values inside the array.

The spread operators allows your to set the constructor parameters.

class Content extends Array {
  delete (index) {
    return [...this.slice(0, index), ...this.slice(index + 1)]
  }

  copy () {
    return new Content(...this);
  }
}

const content = new Content('alpha', 'beta', 'gamma')
const copy = content.copy()
console.log(copy.delete(1)) // ["alpha", "gamma"]

EDIT: Please see comment below for potential issues with this solution

klugjo
  • 19,422
  • 8
  • 57
  • 75
  • 1
    Unfortunately, using the Array constructor has some problems. `new Array(3)` will give an array with 3 empty slots, and no array-index own-properties, so `new Content(...this)` where the `...this` resolves to an array index won't work. – CertainPerformance Sep 21 '20 at 17:28
  • Thanks for the insightful comment. I had already upvoted your answer. Will leave my answer here with the EDIT so people can have a look – klugjo Sep 21 '20 at 17:32
  • The usual solution is to use `Array.of` instead somehow. Maybe `Array.of.apply(Content, this)`, not sure if that would work. Or `Object.assign(Object.create(Content.prototype), this)` – CertainPerformance Sep 21 '20 at 17:38