1

I'm noticing that this references something else inside a function that I added as event listener. I read this informative resource and a few questions on stackoverflow but I don't know how to apply it to my case (I'm quite new to the "oop" and the module pattern in javascript so I'm a bit lost).

Here is my little module:

var myModule = myModule || ( function() {
  // Adds event listener for all browsers
  // see http://stackoverflow.com/a/6348597 
  function addEvent( element, event, listener ) {
    // IE < 9 has only attachElement
    // IE >= 9 has addEventListener
    if ( element.addEventListener ) {
      return element.addEventListener( event, listener, false );
    } else if ( element.attachElement ) {
      return element.attachElement( "on" + event, listener );
    }
  }

  return {
    init: function() {
      // Add event listeners
      addEvent(
        document.getElementById( "myElementId" ),
        "click",
        this.processMyElement
      );
      addEvent(
        document.getElementById( "myOtherElementId" ),
        "click",
        this.processMyOtherElement
      );
    },
    hideElementById: function( elementId ) {
      document.getElementById( elementId ).style.display = "none";
    },
    showElementById: function( elementId ) {
      document.getElementById( elementId ).style.display = "block";
    },
    processMyElement: function() {
      this.hideElementById( "myElementId" );
      this.showElementById( "myOtherElementId" );
    },
    processMyOtherElement: function() {
      // Do something else...
    }
  };
}() );

The thing is that this which I use to call hideElementById in processMyElement is referencing to the element I added an eventListener to, and not to the current object.

I tried a few things without success:

  • removing the return in addEvent,
  • using var that = this as a private property of the module (placed in the module before the addEvent definition) and using that in processMyElement
  • using apply in the init method but it (obviously) calls processMyElement when adding the listener to the element

Could anyone help me with this? I tried a few things but I cannot see how to do it better...

PS: I try to build testable code, that's why I had those hideElementById and showElementById methods, in order to separate various functionalities (that may be quite clumsy actually but that's where I am ATM...).

user7890
  • 147
  • 2
  • 11

1 Answers1

0

There are (more than) a couple of common ways to get the correct this binding. For example, you can use a closure:

  var that = this;
  addEvent(
    document.getElementById( "myOtherElementId" ),
    "click",
    function () {
      that.processMyOtherElement();
    }
  );

Or you could use bind:

  addEvent(
    document.getElementById( "myOtherElementId" ),
    "click",
    this.processMyOtherElement.bind(this)
  );

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

Which one you use would depend on other factors.

1800 INFORMATION
  • 131,367
  • 29
  • 160
  • 239
  • Does it mean that if I use those solutions I can continue to use `this` when calling the object methods inside its methods? Eg. calling `hideElementById` using `this.hideElementById()` in `processMyElement`? I tried calling `that.hideElementById()` in `processMyElement` but got `ReferenceError: that is not defined` which confuses me because I thought `that` was an alias for this and would be used everywhere in the methods in order to avoid problems with `this` referencing something else... – user7890 Nov 12 '15 at 09:45
  • `that` is an alias for `this` in the scope with which it is defined. `var` has function scope, so `that` is defined only within the function `init` where it is defined. Inside the `processMyElement` function, you will be able to use `this`. – 1800 INFORMATION Nov 12 '15 at 18:29