# Allow apply() and call() of Class Constructors

**URL:** <https://es.discourse.group/t/allow-apply-and-call-of-class-constructors/1286>\
**Category:** 💡 Ideas\
**Created:** [April 8, 2022, 10:28pm UTC](https://es.discourse.group/t/allow-apply-and-call-of-class-constructors/1286 "2022-04-08T22:28:38Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Bagel03](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bagel03/32/1331_2.png) [@Bagel03](https://es.discourse.group/u/Bagel03)\
**Post date:** [April 8, 2022, 10:28pm UTC](https://es.discourse.group/t/allow-apply-and-call-of-class-constructors/1286/1 "2022-04-08T22:28:39Z")

</div>

The Old Way:

In the past, all classes were defined as such:

```javascript
function MyClass(num) {
    this.num = num;
}

MyClass.prototype.add1 = function() {
    this.num++;
}

let one = new MyClass(1)
one.add1();

```

Constructors were defined as normal functions and only returned new objects when the `new` operator was used. When the `new` operator was used, the function would:

1. Create a blank, plain JavaScript object.
2. Add a property to the new object (` __proto__ `) that links to the constructor function's prototype object
3. Bind the newly created object instance as the `this` context (i.e. all references to `this` in the constructor function now refer to the object created in the first step).
4. Run the constructor function
5. Return `this` if the function doesn't return an object.

What this means (for the sake of this idea) is that the 3rd and 4th steps were essentially `Constructor.apply({}, prams)`. This operation was also valid on its own, which is the point of this idea:

```javascript
MyClass.apply(one, [5]); // Now the "num" value is 5
MyClass.addOne()

```

New `class` Declerations:

In some situations, it would be useful to use these internal steps with newer `class` declarations. Consider [Object Pooling](https://egghead.io/blog/object-pool-design-pattern), where all pooled objects require a reset method. This leads to lots of classes that look like this:

```javascript
class MyClass {
    constructor(num) {
        this.reset(num)
    } 
    reset(num) {
        this.num = num;
    }
}

```

Less readable, and not useful at all if you have 3rd party libraries. We can not do the same trick as above (reusing the constructor as a reset method), because _Class constructor MyClass cannot be invoked without 'new'_. This is an error thrown whenever a class is called as a function (`MyClass()`) which also happens when using `apply` and `call`. I suggest that this restriction be removed for cases where `apply` or `call` is used with an already created instance of that class.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [April 8, 2022, 10:42pm UTC](https://es.discourse.group/t/allow-apply-and-call-of-class-constructors/1286/2 "2022-04-08T22:42:11Z")

</div>

See the first item on [https://github.com/tc39/proposals/blob/aa528b17cb104d80c4be3f9539f47fd1486df3cc/inactive-proposals.md](https://github.com/tc39/proposals/blob/main/inactive-proposals.md)

---

<div class="post-metadata">

**Author:** ![Bagel03](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bagel03/32/1331_2.png) [@Bagel03](https://es.discourse.group/u/Bagel03)\
**Post date:** [April 8, 2022, 11:22pm UTC](https://es.discourse.group/t/allow-apply-and-call-of-class-constructors/1286/3 "2022-04-08T23:22:13Z")

</div>

That is useful if you want `new Date()` and `Date()` to do the same thing, I want the constructor to do everything except for creating a new object (which is not possible with decorators)

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [April 8, 2022, 11:44pm UTC](https://es.discourse.group/t/allow-apply-and-call-of-class-constructors/1286/4 "2022-04-08T23:44:03Z")

</div>

How would private fields be handled? Normally you can't add new private fields to an existing object. But, if I take an instance of one class, then use `.call()` to give that same instance to a bunch of other class constructors, are new private fields going to be installed onto the same instance? Or, would it fail as soon as a class tries to install an extra private field? This is an interesting can of worms.

I'm also not positive a change like this can be made for all existing classes. Some classes could be designed with the expectation that it will always receive an empty object as "`this`" when its constructor is run. A change like this could allow users to abuse classes in new way that wasn't previously possible, which normally isn't a big deal, but if that class is supposed to be part of something security-sensitive, where untrusted code is running and using these classes, we're now providing a new attack vector for users to potentially dig into the class in new ways. So, such a feature would probably have to be opt-in instead of "automatically applies to every class that's been created".

---

<div class="post-metadata">

**Author:** ![Bagel03](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bagel03/32/1331_2.png) [@Bagel03](https://es.discourse.group/u/Bagel03)\
**Post date:** [April 9, 2022, 12:07am UTC](https://es.discourse.group/t/allow-apply-and-call-of-class-constructors/1286/5 "2022-04-09T00:07:13Z")

</div>

What if you limited it to only working on the original object's constructor (or one of the constructors that the object is derived from).

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [April 9, 2022, 12:24am UTC](https://es.discourse.group/t/allow-apply-and-call-of-class-constructors/1286/6 "2022-04-09T00:24:58Z")

</div>

Is there another use case besides the one listed? That use case seems fairly niche. It's not common to want to bypass JavaScript's built-in garbage-collector like that and try and put control of garbage collection into your own hands. If you really need to do this, you can with that pattern, but from what I understand, you wouldn't use that specific pattern for many different types of classes, so it doesn't seem like a ton of boilerplate to have "`constructor(...args) { this.reset(...args) }; reset(...) { ... }`" in the handful of classes that need to be able to participate in this alternative memory-management system.

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [April 9, 2022, 12:28am UTC](https://es.discourse.group/t/allow-apply-and-call-of-class-constructors/1286/7 "2022-04-09T00:28:53Z")

</div>

Also, you might be interested in [this thread](https://es.discourse.group/t/exposing-existing-gc-functionality-with-gc-criticalhint-and-gc-collecthint-pause-hints-for-realtime-javascript/703), which talks about exposing an API to give hints to a garbage collection, like asking the garbage collector to refrain from running for a period of time. This could help remove some of the need for this sort of custom memory management.

---

<div class="post-metadata">

**Author:** ![Bagel03](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bagel03/32/1331_2.png) [@Bagel03](https://es.discourse.group/u/Bagel03)\
**Post date:** [April 9, 2022, 12:29am UTC](https://es.discourse.group/t/allow-apply-and-call-of-class-constructors/1286/8 "2022-04-09T00:29:04Z")

</div>

It could be useful for any instance where you want to reset an object to its original state, for example resetting a transformation. It might also not be much boilerplate for you, it would be useful for old libraries that are not updated for this (and require you to redo the entire constructor inside a new reset function)

---

<div class="post-metadata">

**Author:** ![theScottyJam](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/thescottyjam/32/616_2.png) [@theScottyJam](https://es.discourse.group/u/theScottyJam)\
**Post date:** [April 9, 2022, 1:18am UTC](https://es.discourse.group/t/allow-apply-and-call-of-class-constructors/1286/9 "2022-04-09T01:18:56Z")

</div>

> It could be useful for any instance where you want to reset an object to its original state

I actually see this more as a disadvantage. Lets take promises as an example:

```javascrip
const promise = doSomeAsyncTask()
givePromiseToSomeone(promise)
await promise

```

When you do `await` promise, are you awaiting the same promise that you received from `doSomeAsyncTask()`? Or, did `givePromiseToSomeone()` reset the promise instance, effectively replacing it with a different promise? Right now, you can know with a fair amount of certainty that it's the same promise (as long as odd monkey-patching isn't going on to make the one instance act like another one). It would be nice if we can keep it this way as much as possible. It's these sorts of guarantees that make it easier to read code, and know that nothing odd is happening. It would be better if we could find more ways to add restrictions to the language and have more of these kinds of guarantees (a rather difficult thing to do without breaking backwards compatibility). Allowing us to reset any class seems like a step in the wrong direction.
