0

Overview

I have the JavaScript classes Parent, Child1, and Child2. Both children extend Parent. I want to write a method that "semi-deep" copies (explained later) the object. Because in actuallity there could be hundreds of children, I'd write this method on the parent and all children inherit that method. But the copy always returns the type that called it.

For instance, the usage would be the following:

const parent = new Parent([1, 2, 3])
const parentCopy = parent.copy() // parentCopy has type Parent
const child1 = new Child1([1, 2, 3])
const child1Copy = child1.copy() // child1Copy has type Child1
const child2 = new Child2([1, 2, 3])
const child2Copy = child2.copy() // child2Copy has type Child2

How can I do this?

What I've tried

If this were not a class, you could use destructuring:

const copy = {...original}

This is the same affect I want. However, since this is a class, I assume I'll need to eventually create a new Thing. For instance, here's how I could create a copy of Parent.

class Parent {
    // ...
    copy() {
        return new Parent()
    }
}

However, this solution means I'd need to override it for every single child. How can I say instead to create a new WhateverThisTypeActuallyis? So if this is a Child1 calling the copy, it'll create a new Child1().

What does "semi-deep" mean?

Briefly, a shallow copy is just a reference to the actual object. For instance, the following code snippet performs a shallow copy.

let object = { a: 2, b: 3 };
let copy = object;
object.a = 5;
console.log(copy.a);

This is not what I want. I want to create a new version of the object. However, I do want to shallow copy any properties the object may have. So I don't need a structured clone which does a recursive deep copy.

Other requirements

This should be pure JavaScript. I cannot use other dependencies or npm packages.

Nick
  • 5,108
  • 2
  • 25
  • 58
  • 1
    Why are there hundreds of subclasses? So far it seems like JS's prototypal model fits your needs better than its "class" model. It also seems pretty sketchy to do a shallow clone where each instance may be sharing data. – Dave Newton Jan 14 '23 at 18:39
  • All the shared data will be immutable. So shallow copying it will be cheaper than deep copying. I'll try and figure out something with prototypes. – Nick Jan 14 '23 at 19:27
  • "*a shallow copy is just a reference to the actual object.*" - no it is not. That is a copy of the reference. A shallow copy does indeed copy the property values onto a new object, but does not deep-clone objects. – Bergi Jan 14 '23 at 22:55

1 Answers1

0

It looks like you can use this.constructor to achieve this effect. It even preserves the children's methods.

class Parent {
  constructor(value) {
    this.value = value
  }

  copy() {
    return new this.constructor([...this.value])
  }
}

class Child extends Parent {
  greet() {
    console.log("hello world")
  }
}

const child = new Child([1, 2, 3])
console.log("child value", child.value)
child.greet()
const copy = child.copy()
child.value.push(4)
console.log("child value", child.value)
console.log("copy value", copy.value)
copy.value.push(4)
console.log("copy value", copy.value)
copy.greet()
Nick
  • 5,108
  • 2
  • 25
  • 58