0

Recently I learned Javascript ES6 has classes so I tried them but my functions were always giving me errors saying they don't exist. So I made pseudo-classes using javascript associative arrays. It was working absolutely fine until I added some new methods.

Here is the error message I'm receiving:

EventListener.js:132 Uncaught TypeError: this.listen_for_tab_swap is not a function
at HTMLDivElement.<anonymous> (EventListener.js:132)
at Object.alert_eventlistener_of_tabs (EventListener.js:41)
at Object.new_tab (EventListener.js:59)
alert_eventlistener_of_tabs @ EventListener.js:41
new_tab @ EventListener.js:59
xhr.onreadystatechange @ EventListener.js:94
XMLHttpRequest.send (async)
(anonymous) @ EventListener.js:101

Here is the relevant code body:

const eventListener = {

     listen_for_tab_swap: function() {
         $(".footer button").on("click", function (event) {
             file_tabs.show_tab(event.target.innerText);
         });
     },

     listen_for_tabs_activation: function() {
         $("#AZ_content").on("tabs_loaded", function () {
             this.listen_for_tab_swap();
         });
     },

     listen: function() {
         $(function () {
             console.log("Yeah, I'm listening...");
             $(".menu").on("click", function (event) {
                 AZ_page_is_opened(event);
                 showTab(event, event.target.id.replace("Button", ""));
             });
         });
     }
 };

Please let me know if there is any additional information required to troubleshoot. Thanks in advance for any help.

lakam99
  • 575
  • 4
  • 9
  • 24
  • 1
    You are not using classes. You are just adding elements to an object that happen to be functions. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes – Luke Feb 28 '20 at 01:13
  • I know. I called them "pseudo-classes". I'm not denying they have a real name. – lakam99 Feb 28 '20 at 01:15
  • You can't use `this` in a normal object. You have to add the functions to a prototype. – Luke Feb 28 '20 at 01:16
  • 1
    @LuketheGeek You can actually use `this` for a normal object, that's how objects work. The problem is `this` in that function is not what the OP expects it to be – slebetman Feb 28 '20 at 01:23
  • @slebetman when I access the eventListener object through my developer console in chrome, it does say that eventListener.listen_for_tab_swap is undefined. – lakam99 Feb 28 '20 at 01:25
  • https://medium.com/better-programming/understanding-the-this-keyword-in-javascript-cb76d4c7c5e8 – Luke Feb 28 '20 at 02:14

1 Answers1

2

In js this is dynamic. It depends on how a function is called. I'm assuming you're using jQuery because it looks like jQuery syntax at a glance so for your specific case all you need to know is that in jQuery (and also in regular javascript) the value of this in an onclick event is the element that triggered the event:

{
  // ...

  listen_for_tabs_activation: function() {
     $("#AZ_content").on("tabs_loaded", function () {
         this.listen_for_tab_swap(); // this is AZ_content
     });
}

In the code above what you are doing is trying to call $("#AZ_content")[0].listen_for_tab_swap() and it is complaining that that HTML element does not have a method called listen_for_tab_swap

There are several ways to fix this. The simplest is probably do:

eventListener.listen_for_tab_swap();

You can also use arrow functions to bind this:

{
  // ...

  listen_for_tabs_activation: function() {
     $("#AZ_content").on("tabs_loaded",() => { // this fixes `this`
         this.listen_for_tab_swap();
     });
}

There are several more ways to solve this. Check out this answer to another related question for how this actually behaves: How does the "this" keyword in Javascript act within an object literal?

slebetman
  • 109,858
  • 19
  • 140
  • 171
  • I figured out the solution from reading only a bit of your answer. You've taught me a great deal. Thank you. – lakam99 Feb 28 '20 at 01:40