1

I'm trying to bind my prototype functions to event listeners, but somehow this isn't working. I'm suspecting this is caused because the scope of the function call is not correct. I have a few issues with this which I made clear with the simplified example below.

Let's say I have the following JavaScript Prototype:

<html>
 <head>
  <script type="text/javascript">
   function BindActionsToHTMLObject(htmlElement) {
    this.htmlElement = htmlElement;
     
    this.setUp = function() {
     this.htmlElement.onclick = this.doAction;
    };
     
    this.doAction = function() {
     console.log(this.htmlElement);
     this.htmlElement.innerHTML += " adding content";    
     setTimeout(this.addContent, 3000);
    };
   }
  </script>
 </head>
 <body>
  <textarea id="usedElement"></textarea>
  <script type="text/javascript">
   var el = new BindActionsToHTMLObject(document.getElementById("usedElement"));
   el.setUp();
  </script>
 </body>
</html>

When I try to bind the onclick event listener to the this.doAction() function I get the error that this.doAction() is not a function. I'd like to do the event binding inside the class since it seems like cleaner coding to me.

However running the protoype functions directly obviously works fine (without event listener). So pratically I could bind the onclick event outside of the prototype...

<html>
 <head>
  <script type="text/javascript">
   function BindActionsToHTMLObject(htmlElement) {
    this.htmlElement = htmlElement;
     
    this.setUp = function() {
     this.htmlElement.onclick = this.doAction();
    };
     
    this.doAction= function() {
     console.log(this.htmlElement);
     this.htmlElement.innerHTML += " adding content";    
     setTimeout(this.doAction, 3000);
    };
   }
  </script>
 </head>
 <body>
  <textarea id="usedElement"></textarea>
  <script type="text/javascript">
   var el = new BindActionsToHTMLObject(document.getElementById("usedElement"));
   el.doAction();
  </script>
 </body>
</html>

This does add the content to the element, however if I call the function in a timeout event the function does get called BUT the reference to the this.htmlElement is null, so I guess the object lost scope again whenever it is passed as an event. What would be the correct method to pass the function? Wrapping it in (function() { this.doAction(); })(); and varieties doesn't help.

Gilles Lesire
  • 1,237
  • 17
  • 33
  • are you sure its not just a typo? `doAction` and `DoAction` ? – Suraj Rao May 11 '17 at 08:30
  • Thanks for addressing that but it is not the reason it fails. Seems like I can retain the scope by bind the "this" object to the function. Like this: (function() { this.doAction(); }).bind(this); Seems unnecessary messy but it works. – Gilles Lesire May 11 '17 at 08:38
  • I don't see any usage of prototypes in that code?! – Bergi May 11 '17 at 08:40
  • @GillesLesire Yes that's unnecessary messy. Just do `this.doAction.bind(this)`. – Bergi May 11 '17 at 08:43
  • Yes exactly haha. Sometimes it is just that obvious. I think a better reference article would be http://stackoverflow.com/questions/2236747/use-of-the-javascript-bind-method – Gilles Lesire May 11 '17 at 11:34

0 Answers0