0

Why can't I refer to a method of a JavaScript object by using "this"? Like for example in open(); method - why can't I call this.init(); ?

    var myModule = {

        //Initialize dek. Append html structure to the body
        init: function() {
            if (!$('.mwdek').length) {
                var dek = $(tpl);
                dek.find('.d-nav-close').on('click', function(e) {e.stopPropagation();e.preventDefault();
                    this.destroy();
                });
                dek.appendTo('body');
            }
            //var dek = $('.mwdek');

        },

        //Opens deck, makes it visible
        open: function() {
            if (!$('.mwdek').length) {
                this.init();
            }
            $('.mwdek').addClass('active');
        },

        //Removes deck html from the page
        destroy: function(messages) {
            $('.mwdek').remove();
        },

        //Pass in header text content
        setHeaderText: function() {

        }


    };
Stephen Docy
  • 4,738
  • 7
  • 18
  • 31
Dannyboy
  • 1,963
  • 3
  • 20
  • 37
  • 3
    Your example should work fine - http://jsfiddle.net/xq17mmzy/ - what won't work is `this.destroy()` because that is inside a callback with a different `this` context – CodingIntrigue Jun 25 '15 at 15:58
  • 2
    If you call `open` as `myModle.open()`, then `this.init()` will work just fine. – Felix Kling Jun 25 '15 at 15:58
  • 2
    You can call `this.init`. I have a feeling your condition isn't true. Remove the condition and see if it gets called. Otherwise I think you are calling it with a different context. Please share how you are trying to invoke `open`. – Matt Derrick Jun 25 '15 at 15:59
  • There shouldn't be any problem with `this.init()` in `myModule.open()`. But [the `this.destroy()` call in that event handler will fail](http://stackoverflow.com/q/20279484/1048572). – Bergi Jun 25 '15 at 16:15
  • why down vote this question? – floor Jun 25 '15 at 16:21

1 Answers1

2

The logic looks good apart from 1 issue in your init function involving the this variable. In a statement like object.method(), within the method function, this refers to object. Keep this in mind.

Now, Here's the problematic portion of your code:

init: function() {
    if (!$('.mwdek').length) {
        var dek = $(tpl);
        dek.find('.d-nav-close').on('click', function(e) {
            e.stopPropagation();
            e.preventDefault();
            this.destroy();     //THIS LINE has the issue!
        });
        dek.appendTo('body');
    }
}

The this variable on the line I commented is inside of an anonymous function you've written (function(e) {...}). This function is provided to JQuery to run when the appropriate click occurs. So JQuery is deciding how to call that function, which means that only JQuery really understands what this will refer to when the function is called. In your code, you rely on this pointing to the instance of dek, but that isn't the case. In order to solve this problem you can do the following (choosing to name the variable that is common convention):

init: function() {
    var that = this; //Maintain a reference to "this" even inside anonymous functions
    if (!$('.mwdek').length) {
        var dek = $(tpl);
        dek.find('.d-nav-close').on('click', function(e) {
            e.stopPropagation();
            e.preventDefault();
            that.destroy();     //Originally "this.destroy();"
        });
        dek.appendTo('body');
    }
}
Gershom Maes
  • 7,358
  • 2
  • 35
  • 55