Naxon
Naxon

Reputation: 1414

Javascript OOP - calling a method from a different method of the same class

I got this code:

class TestClass = function() {
    var methodOne = function(a, b) {
        return (a == b);
    }

    var methodTwo = function() {
        var elements = $('.element');

        elements.droppable({
            drop: function(event, ui) {
                if (!this.methodOne(ui.draggable.data('a'), ui.draggable.data('b'))) {
                    return false;
                }

                return true;
            }
        });
    }
};

When running this, I get the following error:

Uncaught TypeError: this.methodOne is not a function

Any ideas why?

Upvotes: 0

Views: 57

Answers (2)

trincot
trincot

Reputation: 351218

Some points to raise:

  1. The syntax of the ES6 classes is different.

  2. You can use bind to fix the this object to the function assigned to drop.

  3. Not related to the problem, but the if in that function really is unnecessary. You can just return the result of the boolean expression:

Code:

class TestClass {
    methodOne (a, b) {
        return (a == b);
    }

    methodTwo () {
        var elements = $('.element');

        elements.droppable({
            drop: function(event, ui) {
                return this.methodOne(ui.draggable.data('a'), ui.draggable.data('b'));
            }.bind(this)
        });
    }
};

Upvotes: 1

inf3rno
inf3rno

Reputation: 26137

Don't confuse javascript with java. By javascript your class does not have private methods, so you cannot access these functions by using the this keyword.

You can do the following:

var TestClass = function() {
    var methodOne = function(a, b) {
        return (a == b);
    }

    var methodTwo = function() {
        var elements = $('.element');

        elements.droppable({
            drop: function(event, ui) {
                if (!methodOne(ui.draggable.data('a'), ui.draggable.data('b'))) {
                    return false;
                }

                return true;
            }
        });
    }
};

but be aware that the methodOne and methodTwo variables don't have values outside the constructor, since they are local variables of the constructor function and not methods.

You can define methods by adding them to the prototype, e.g.:

TestClass = function() {};
TestClass.prototype = {
    constructor: TestClass,
    methodOne: function (){...},
    methodTwo: function (){...}
};

In this case the this keyword works if you call the methodOne from the methodTwo, but in your example you call it from a function defined in the methodTwo, so you have to use the bind() function to create a wrapper which sets the context by that function.

var TestClass = function() {
};
TestClass.prototype = {
    constructor: TestClass,
    methodOne: function(a, b) {
        return (a == b);
    },
    methodTwo: function() {
        var elements = $('.element');

        elements.droppable({
            drop: function(event, ui) {
                if (!this.methodOne(ui.draggable.data('a'), ui.draggable.data('b'))) {
                    return false;
                }

                return true;
            }.bind(this)
        });
    }
};

If you want to use ES6 classes instead of ES5, then the story is somewhat different, but you'll need a compiler e.g. babel, traceur, etc... As far as I know you cannot use the class keyword by ES5, so you should use var instead of that.

Upvotes: 1

Related Questions