0

Note: I do not want to re-bind the this keyword. I would like for this to reference the calling object. I would, however, also like to be able to reference the instance of the class in which my method is defined. How can I access the instance?

In JavaScript, the this keyword refers to the calling object. So, when I define a class:

class A {
    x = 5;
    printx() {
        console.log(this.x);
    }
}

Then when I call the printx method directly from an instance of A, I get 5:

a = new A();
a.printx();

But when I call printx from a different context, this.x isn't a.x, it might be window.x or something else:

b = a.printx;
b(); // TypeError: this is undefined

I want to define printx in such a way that calling b will console.log(5). I.e., I want to get the self behavior from Python. How do I refer to self in JavaScript?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Him
  • 5,257
  • 3
  • 26
  • 83
  • 3
    The top answer here is much more complete that the ones linked in the top: https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback – felipou Oct 19 '22 at 20:59
  • @felipou the answer in that question never defines a `class`. I realize this is just syntactic sugar over old-style javascript classes, but it makes the answers in your link difficult to parse. i.e. in order to know the answer to my (simple) question, I must understand difficult and deep concepts and also grok the history of the javascript language. – Him Oct 19 '22 at 21:08
  • "this is not possible" is also an acceptable answer. – Him Oct 19 '22 at 22:48
  • it's very possible, though usually it's best to avoid the scenario. (aka don't do `b = a.printx;`) – Kevin B Oct 20 '22 at 14:48
  • @KevinB my specific use case is that I'm using my class method as a callback. (i.e. the method gets passed in as a parameter to another function) – Him Oct 20 '22 at 14:51
  • 1
    Right, in cases such as that, you pass a different function that calls the method. For example, `foo={() => a.printx()}` (in a react context.) in vanilla it'd be something like: `.then(() => a.printx())` – Kevin B Oct 20 '22 at 14:54
  • @KevinB "it's very possible, but avoid" - would you mind elaborating on this? Are you suggesting that there are common scenarios where I might want to have my `printx` method print `.x` from *a different object*? As a python programmer, one might do something like `A.printx(something_else_with_an_x_property)` to get similar behavior to the above (i.e. the `self` in `printx` would not necessarily be an instance of `A`, it could be whatever I want in the context of using it.) However, I see this sort of thing only *very rarely*... – Him Oct 20 '22 at 15:04
  • 1
    arrow functions would generally be the way of solving this, however that's not a thing for class methods *yet,* so in your case you would need a constructor that does something along the lines of `this.printx = () => console.log(this.x)` or `this.printx = this.printx.bind(this)`, causing the function referenced by this.printx to be directly bound to that instance rather than the context of the reference. – Kevin B Oct 20 '22 at 15:13
  • 1
    this may actually be a thing now, not sure... haven't been keeping up with the js releases the last few years. if it is, then you'd simply change `printx() {` to `printx = () => {` – Kevin B Oct 20 '22 at 15:19

1 Answers1

5

Use function.prototype.bind to bind the function to the context when you assign b

class A {
    x = 5;
    printx() {
        console.log(this.x);
    }
}

let a = new A()
let b = a.printx.bind(a)

b()
Brother58697
  • 2,290
  • 2
  • 4
  • 12