0

Please note this question is not talking about previous versions of react as in this 2017 question Reactjs: In JavaScript, class methods are not bound by default


In reactjs docs on Handling events, they mention the following for this example

In JavaScript, class methods are not bound by default. If you forget to bind this.handleClick and pass it to onClick, this will be undefined when the function is actually called.

I think the bold statement is technically incorrect. Consider the following example:

class component2 {
  prop = 3;
  foo() {
    console.log(this.prop);
  }
}
var obj = new component2();
obj.foo();
<button id="one">Print prop</button>

As you can see I didn't have to bind this. This contradicts react18 documentation and also contradicts react2017 answer

user31782
  • 7,087
  • 14
  • 68
  • 143
  • 2
    Your example is wrong. It calls the method *on the object instance*. The quote refers to passing them as references. [See here](https://jsbin.com/royoyusivi/1/edit?html,js,console,output). This is what you'd get if you did ` – VLAZ Sep 14 '22 at 07:12
  • Interesting! the marked duplicates are not about react js. They don't explain why is `this` not bound by default in react js, as I have already proved that (contrary to react docs) In JavaScript, class methods are not bound by default. – user31782 Sep 14 '22 at 07:12
  • "*why is this not bound by default in react js,*" React is not a separate language, or environment, or runtime or anything. It's a plain library that works by the normal JS rules. – VLAZ Sep 14 '22 at 07:13
  • 1
    https://codepen.io/tushar8/pen/abGBJBq?editors=0011 This is what actually happens – Tushar Shahi Sep 14 '22 at 07:14
  • 1
    Notice, `obj.bar()` is not called on click. But `bar` is. – Tushar Shahi Sep 14 '22 at 07:14
  • `this` will not be the global object, but `undefined` because ES6 classes run in strict mode. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode#strict_mode_for_classes – Tushar Shahi Sep 14 '22 at 07:15
  • @VLAZ react is js but we are dealing with babel and JSX here. From your example it seems like react is converting `onClick` to `addEventListener("click")` behind the scenes, in which case yes `this` should work as you say. But react docs statement `In JavaScript, class methods are not bound by default` is a general statement about js classes not about event listeners. – user31782 Sep 14 '22 at 07:17
  • 1
    When they say React methods are not bound by default, they mean - If you call `bar` somewhere else it would have no idea of its original `this`. It has no default binding of `this` and that value of `this` is based on how it is called. The link attached by @VLAZ explain the same thing. How the value of `this` is determined – Tushar Shahi Sep 14 '22 at 07:18
  • @user31782 and...so? It's still correct. And explained in the duplicates. If you *don't* want to focus on react or components, then [here is an even simpler example](https://jsbin.com/bameyotuye/1/edit?js,console) that demonstrates that `this` is not bound. I do not understand what *you* don't understand here. `this` is late-bound - at call time. Unless it's in an arrow function, which uses lexical binding. That's explained in the duplicates. The statement you quoted is correct. – VLAZ Sep 14 '22 at 07:20
  • @TusharShahi I understand this for the event listeners stuff, but my question is not about event listeners. I am going to delete that from my question and make it clear that I am asking about classes and their methods, not about event listeners. – user31782 Sep 14 '22 at 07:20
  • ok ok, I think what react docs mean is this: *In JavaScript, class methods are not bound by default, i.e. if those class methods are called without the context of their object*. – user31782 Sep 14 '22 at 07:25
  • 2
    This is not specifically related to reactjs. It is about the very foundation of JavaScript: functions don't *belong* to a certain class/prototype, like you would expect in other languages. It is not even specific for `class`: it is the same principle for functions defined "old style" on a constructor's `prototype`, or functions defined as object properties in an object literal. It's all the same principle. – trincot Sep 14 '22 at 07:25
  • @trincot but most of the time we call object's function with an object like `obj.foo()`, we can't usually call `foo()`. For the most part functions/methods of a class are bound to their objects. It's just that when we use `bind` or `apply` that this binding changes. Or if the method happens to be returning another function, then that another function would get executed outside of the object context. – user31782 Sep 14 '22 at 07:34
  • "*For the most part functions/methods of a class are bound to their objects.*" no, they *aren't*. That's what late binding is *and the very quote you wanted to discuss*. "*It's just that when we use bind or apply that this binding changes*" or ***EXTRAORDINARILY VERY COMMON*** when you pass a method as a reference when a callback is needed. This kind of problem is one of the highest asked about on SO in the JS-family tags. I don't get what you're trying to advocate for here - that behaviour *that is proven to you multiple times* does not exist? – VLAZ Sep 14 '22 at 07:38
  • @VLAZ WHat you mean by _when you pass a method as a reference_? I don't think we can pass references in js. I am not advocating anything, I have just asked a question to more knowledgeable people about what reactjs docs mean by _In JavaScript, class methods are not bound by default_. – user31782 Sep 14 '22 at 07:41
  • "*WHat you mean by when you pass a method as a reference?*" `.addEventListener("click", obj.foo)` which was my first example to you. And one of the most common types of problems. And explain *in depth* in [How to access the correct `this` inside a callback](https://stackoverflow.com/q/20279484) which is [the fourth most frequent JS question](https://stackoverflow.com/questions/tagged/javascript?tab=Frequent) because we get a dozen or two a day of these where users did some variation of `functionThatTakesCallback(obj.someMethod)` and got the wrong value for `this`. – VLAZ Sep 14 '22 at 07:46
  • "*I have just asked a question to more knowledgeable people about what reactjs docs mean by In JavaScript, class methods are not bound by default.*" which was explained rather thoroughly with supporting materials and examples. Only for you to turn around and say that it's not true. Hence my question - what are you advocating for? Because if you wanted knowledge, you've been supplied with it. If you're disputing it *in face of facts*, then that doesn't seem like asking for knowledge to me. – VLAZ Sep 14 '22 at 07:47
  • @VLAZ I don't think `.addEventListener("click", obj.foo)` is a pass by reference. js doesn't have this feature like other classical languages where you use `function(&reference)` – user31782 Sep 14 '22 at 07:49
  • [What is the difference between a function call and function reference?](https://stackoverflow.com/q/15886272) – VLAZ Sep 14 '22 at 07:51
  • Those answer don't seem to be legit, they don't have any documentation references to back them up. I think they are misusing the term `reference`. – user31782 Sep 14 '22 at 07:52
  • 1
    The value of an object is its reference. Functions are objects. Ergo, passing `fn` as an argument, supplies the called function with the reference to `fn`. But since this all seems to be just you arguing against long-established, well-documented, facts about JS, that's the last of me. I feel I'm wasting my time having to explain and justify concepts and all I get is arguments that it's wrong to which I have to dig out more resources. I'm not here to have to argue facts exist. – VLAZ Sep 14 '22 at 07:58

0 Answers0