1

I'm implementing a class-like structure in jQuery, but I'm having some trouble when I try to call some of my functions.

This is how the structure is setup:

MyClass = function(name) {
    this.init(name);
}
$.extend(MyClass.prototype, {
    init: function(theName) {
        this.myFunction(); // works
        $('.myclass').each(function(){
            this.myFunction(); // doesn't work
        });
    },
    myFunction = function(){}
});

The problem I'm having is that when I try to call one of my functions (e.g., myFunction()) from inside a jQuery block (like the each() construct above), I get the error "myFunction() is not a function."

I think this has something to do with the this keyword changing its meaning inside the jQuery block, but I'm not sure. Any help would be appreciated!

Tyler Carter
  • 60,743
  • 20
  • 130
  • 150
Josh Leitzel
  • 15,089
  • 13
  • 59
  • 76
  • @Bergi so this question is a duplicate of a question that was posted more than 4 years after it? Nice. – Josh Leitzel Aug 06 '15 at 21:45
  • Yes, that question from 2013 is a canonical reference, explaining the problem that you also had and all (sic!) solutions to it extensively. Please don't feel offended, you've done nothing wrong :-) I'm just directing future readers to the canonical. – Bergi Aug 06 '15 at 21:52
  • I'm not offended, and I definitely understand! ;) It just sucks that the copy around this feature makes it seem like the OP sloppily asked a question that already had an answer – "This question already has an answer here:" "This question has been asked before and already has an answer." Just a little weird. – Josh Leitzel Aug 06 '15 at 23:18
  • Yeah, it really should say something like "*This question has a better answer here*" or so. See also [my MSO post](http://meta.stackoverflow.com/q/285177/1048572) – Bergi Aug 06 '15 at 23:25
  • Ah, very nice. Gave you a +1 over there. – Josh Leitzel Aug 06 '15 at 23:28

3 Answers3

4

You need to assign this to another variable, because of how scope works.

MyClass = function(name) {
    this.init(name);
}
$.extend(MyClass.prototype, {
    init: function(theName) {
        this.myFunction(); // works
        var that = this;
        $('.myclass').each(function(){
                this.myFunction(); // doesn't work
                that.myFunction(); // should work
        });
    },
    myFunction = function(){}
});
Tyler Carter
  • 60,743
  • 20
  • 130
  • 150
0
MyClass = function(name) {
    this.init(name);
}
$.extend(MyClass.prototype, {
    init: function(theName) {
        this.myFunction(); // works
        temp = this;
        $('.myclass').each(function(){
                temp.myFunction(); // works
        });
    },
    myFunction = function(){}
});

Try that. :)

Salty
  • 6,688
  • 3
  • 33
  • 31
0

The .each() function changes the context of this (as does any function in JavaScript).

You need to do something like this:

MyClass = function(name) {
    this.init(name);
}
$.extend(MyClass.prototype, {
    init: function(theName) {
        this.myFunction(); // works
        var myClass = this;
        $('.myclass').each(function(){
                myClass.myFunction(); // doesn't work
        });
    },
    myFunction = function(){}
});
VoteyDisciple
  • 37,319
  • 5
  • 97
  • 97