Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind the "this" of a class constructor to an external object

Tags:

javascript

I am looking for a way to use something similar to Function.apply for classes so that the this property of an executed constructor is an external object.

With a function I can simply use apply

function Bar() {
  this.value = 'value'
}

const proxy = {}
Bar.apply(proxy, [])

console.log(proxy) // { value: 'value' }

However this does not, of course, work with classes

class Foo {
  constructor() {
    this.value = 'value'
  }
}

const proxy = {}
Foo.apply(proxy, [])

console.log(proxy)

Resulting in

Foo.apply(proxy, [])
    ^
TypeError: Class constructor Foo cannot be invoked without 'new'

Is it possible to bind the this context of a class constructor to another object?

I don't have any legacy clients so I am able to use Reflect.construct (though I am not sure if it can solve the problem)

EDIT:

Alternatively, I can work with replacing this after construction. Is that possible?

const foo = new Foo()
foo.bind(proxy)
like image 688
David Alsh Avatar asked Feb 03 '26 10:02

David Alsh


1 Answers

If you have a look at [[Construct]] of function objects (which is the internal method which will be executed when you use new or Reflect.construct), then you'll find this step in the specification:

Let thisArgument be ? OrdinaryCreateFromConstructor(newTarget, "%Object.prototype%").

As there is no way to change this behavior, you cannot change what thisArgument is, it is always a regular object and cannot be a proxy. However, if you use Reflect.construct, you can influence the newTarget, and pass something else in than the regular constructor:

class Constructed {} // this is the function object that will be [[Construct]]ed
class Trapped {} // the "thisArgument" will inherit Trapped.prototype

Reflect.construct(Constructed, [], Trapped);

By injecting a proxy into Trapped.prototype you can have some reflection onto this inside a class constructor. An example can be found here.

like image 159
Jonas Wilms Avatar answered Feb 05 '26 23:02

Jonas Wilms



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!