Search code examples
javascriptthiscustom-element

JavaScript: Method That's Never Loses Binding


Consider this basic custom element:

class XElement extends HTMLElement {
  constructor() { super(); }
  foo() { console.log( this ); }
} customElements.define( 'x-element', XElement );

Here is the problem:

const xelem = new XElement();

/* `foo` will lose its binding to `xelem`:
*/ someButton.onclick = xelem.foo;

// These will work, but it's too verbose:
someButton.onclick = () => xelem.foo();
someButton.onclick = xelem.foo.bind( xelem );

I see only one solution is to add foo as arrow function in constructor, but it seems to me wrong.

constructor() {
  super();
  this.foo = () => console.log( this );
}

Is there any right way to create method that will never lose its binding?


Solution

  • That is how JavaScript this binding works.

    You can read this: THIS (YDKJS) Basically, the value of this inside a function depends upon how that function is invoked. So you need to explicitly hard bind the this value to your function foo by using the bind() method or defining foo as arrow function (arrow functions lexically bind their context).

    So the solution is what you found.

    You can do:

    In your constructor:

    class XElement extends HTMLElement {
      constructor() { 
       super(); 
       this.foo = this.foo.bind(this);   
      }
      foo() { console.log( this ); }
    }
    

    Or (I don't like this one)

    class XElement extends HTMLElement {
      constructor() { 
       super(); 
       this.foo = () => console.log(this);   
      }
    }
    

    Or

    class XElement extends HTMLElement {
      constructor() { super(); }
      foo = () => { console.log( this ); }
    }