1

How does one clone an existing class (not the instance of a class)?

class Base {
  constructor(input='base') {
    this.base = input
  }
}

class CloneBase {
  constructor(input='CloneBase') {
    this.base = input
  }
}

class A extends Base {
  get a() {
    return "a"
  }
}

const Clone = A // how does one clone A?

Object.setPrototypeOf( Clone, CloneBase )

const a = new A()
console.log(a.base) // should be "Base"

const clone = new Clone()
console.log(Clone.base) // should be "CloneBase"

I could use an instance of the class, but that bypasses the constructor in subsequent code and can't be used with new Clone(whatever)

2 Answers 2

1

You cannot clone a class in javascript. Lets take a look at this example:

function classCloner(x) {
  var constructor = function() {
    if(!(this instanceof constructor)) throw new TypeError("Not a constructor");
    x.apply(this, Array.prototype.slice.call(arguments));
  }
  for(var attr in x) {console.log(attr);
    if(Object.hasOwnProperty(attr)) constructor[attr] = x[attr];
  }
  constructor.prototype = Object.create(Object.getPrototypeOf(x.prototype));
  for(var attr in x.prototype) {
    if(Object.hasOwnProperty(attr)) constructor.prototype[attr] = x.prototype[attr];
  }
  return constructor;
}

This function doesn't work:

  1. ECMA6 classes uses checks in the constructor and member functions, so that you cannot directly invoke the class without new. It checks if this instanceOf constructor
  2. If you clone a class, you need to clone all properties. Many properties are functions and they only work with one type, creating multiple types could cause weird errors.

Still there is a way to clone an ECMA6 class, using eval.

var clonedClz = eval(oldClz.toString());

This will clone all properties of the class, and will clone all functions. When oldClz is modified after it was created (e.g oldClz.foo = () => 'bar'), then that change will not apply to the cloned class.

This works, only for ecmascript6 classes, and not for plain js classes. Creating multiple types with the same functions can cause big issues.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks that is the solution: const clsString = (${A.toString().replace("A extends Base", "Clone extends CloneBase")}) const Clone = eval(clsString)
0

Object.assign

let clone = Object.assign( Object.create( Object.getPrototypeOf(orig)), orig)

Please visit this link to more info.

4 Comments

OP asked for the class, not the instance.
This solution bypasses the class constructor, which I want to execute as per usual. Also, it creates a new object at instantiation which I believe will not be as performant as having a predefined class instantiated via new [but I may be wrong]. But thanks for the answer.
welcome @TrevTheDev , glad to know that you could resolved it.
@kk4You no the problem is not solved, as there seems to be no way to duplicate a class

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.