smarber
smarber

Reputation: 5074

Reactjs: In JavaScript, class methods are not bound by default

I'm following handling-events documentation, and I came across this:

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.

What I understand from this quotation is that this doesn't designate the current instantiation in every class methods.

However, if I consider the code below, the method editState can access the property state of the extended class Parent through this. Which would make false the previous quotation, as this is bound to all the class mehtods.

class Parent {
  constructor() {
    this.state = false;
  }
  
  setState(newState) {
    this.state = newState;
  }
}

class Child extends Parent {
  editState() {
    this.setState(true);
  }
}

let c = new Child;
c.editState();
console.log(c.state);

What am I missing here?

Upvotes: 14

Views: 2901

Answers (3)

Jamal Meizongo
Jamal Meizongo

Reputation: 1

William's answer is the most correct after following the link he provided. I'm just posting this to save anybody the time. It is quite a read. Regarding this question when you pass a function as a variable, you need to be careful about the context it is going to be used in.

From my understanding, when a method is fired from a class it's 'this' gets bound to the class object. When it is fired from an event handler it's 'this' gets bound to the button element that fired the event. Since button elements aren't javascript objects, they do not have a 'this' property hence the undefined value.

Upvotes: 0

jyapx
jyapx

Reputation: 2509

I think the React documentation might be misleading. The React component below MyClass is a derived class (aka child class) of React.Component. The constructor method is a special method within javascript ES6 which is used for creating and initializing an object created with a class. React uses the constructor to pass props to the component when the object is created. Base classes (aka parent classes) are created bound to their own this, but the derived classes do not have their own this by default. The derived class must call super(props) which binds the this from the base class down into the derived class.

class MyClass extends React.Component{
    constructor(props) {
       super(props)
    }
}

Here is the relevant information from the link provided by user376830's answer. This is straight from the javascript documentation.

Class context

The behavior of this in classes and functions is similar, since classes are functions under the hood. But there are some differences and caveats.

Within a class constructor, this is a regular object. All non-static methods within the class are added to the prototype of this:

class Example {
    constructor() {
      const proto = Object.getPrototypeOf(this);
      console.log(Object.getOwnPropertyNames(proto));
    }
    first(){}
    second(){}
    static third(){}
}

 new Example(); // ['constructor', 'first', 'second']

Note: Static methods are not properties of this. They are properties of the class itself.

Derived classes

Unlike base class constructors, derived constructors have no initial this binding. Calling super() creates a this binding within the constructor and essentially has the effect of evaluating the following line of code, where Base is the inherited class:

this = new Base();

Warning: Referring to this before calling super() will throw an error.

Derived classes must not return before calling super(), unless they return an Object or have no constructor at all.

class Base {}
    class Good extends Base {}
    class AlsoGood extends Base {
    constructor() {
        return {a: 5};
    } 
 }

class Bad extends Base {
    constructor() {}
}

new Good();
new AlsoGood();
new Bad(); // ReferenceError

Upvotes: 2

William
William

Reputation: 176

When a function is used as an event handler, its 'this' is set to the element the event fired from. As a DOM event handler

Upvotes: 16

Related Questions