0

I am writing an object pool class that holds onto old unused objects, and when a new one is needed can use one of its reserves (Without the expensive creation of objects). However, I want to be able to save any data to this pool (not limited to something such as extends Poolable). The problem is that most object pools require something like this:

class MyData {
    constructor(str) {
        this.reset(str)
    } 
    reset(str) {
        this.str = str;
    }
}

So that when a new instance is needed, the pool can call oldInstance.reset(prams). As stated before, I do not want this (Working with lots of third party tools that I am not feeling like writing wrappers for), so my data looks like this:

class MyData {
    constructor(str) {
        this.str = str;
    } 
}

When the pool needs to reset an instance, I need to be able to call the constructor as a function and set the this value to the instance that is being wiped.

This is super easy with old classes that used function/prototype syntax when they were made:

const MyClass = function(str) {
    this.str = str;
}

// Reset an instance
const instance = new MyClass("foo");
MyClass.apply(instance, ["bar"])
// done

However when I do that for classes, it complains that you can not use a class without the new keyword. How do I go about doing this?

Fiddle: https://jsfiddle.net/wuqek405/

Edit: As I said, most object pools need a reset function. I am trying to use the constructor as this function, because it is supposed to “set up” the instance. Another solution would be to generate this reset function based on the class. However, I want it to be as fast as possible, so terribly hacky solutions such as stringifying the class and evaling the constructor wouldn’t be optimal.

Bagel03
  • 725
  • 7
  • 22
  • 1
    Why do you have to do it by calling the constructor? Why can't you call a method like `reset()`? What are these third-party tools that require this usage? – Barmar Apr 06 '22 at 21:39
  • 2
    You can't. Don't use the class keyword, or reset your pool objects. – Jared Smith Apr 06 '22 at 21:39
  • "*Without the expensive creation of objects*" - is it actually that expensive, have you benchmarked your code? Modern engines have good garbage collectors and optimised object creation. – Bergi Apr 08 '22 at 18:56

1 Answers1

0

This is not possible. A class is not callable1, only constructable - which means creating a new object. This was new in ES6, which overhauled the inheritance model of classes and introduced super. Also, ES2022 will introduce class fields, which also get created during construction without being mentioned in the constructor code.

Your only option is to use only ES5 function-based classes, a transpiler, or writing explicit reset methods.

1: technically, it is callable (typeof C == 'function'), but [[Call]] will always throw an exception

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Is there some way to auto-generate a reset function then? – Bagel03 Apr 08 '22 at 19:27
  • @Bagel03 As soon as private class fields enter the picture, probably not. (Unless you want to generate it at build time, like a transpiler does, and replace the whole class with one that has an extra `reset` method). Otherwise, yes, you could use some brittle string manipulation magic based on `toString()`+`new Function` (to be run once when creating the pool, not on every reset). – Bergi Apr 08 '22 at 19:33
  • Is there a `toString()`+`new Function` solution that wouldn't be screwed over by strings, comments, or spaces? – Bagel03 Apr 08 '22 at 20:34
  • However, that might not even work if a constructor needs outside information (`let a = 0; class B { constructor(num) { this.num = num + a} }` would give us the function `function(num) {this.num = num + a} ` and would fail because a is NaN in this scope) – Bagel03 Apr 08 '22 at 21:17
  • That's why I wrote "brittle", yes :-) Something that won't be screwed over by syntax would have to use a proper JS parser like Babel, and yes it would still have the scope issue you mentioned. Therefore: write it manually, or use `function` constructors. You shouldn't need to use object pools that often anyway, they always require some manual work. – Bergi Apr 08 '22 at 22:50
  • Ah, I just saw [your thread on esdiscourse](https://es.discourse.group/t/allow-apply-and-call-of-class-constructors/1286) :-) – Bergi Apr 09 '22 at 07:04