0

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?

4
  • 1
    It's because this is no longer the TestClass, but specifies the this on drop(event, ui), add var self = this; below var elements, and call self.methodOne() Commented Aug 21, 2016 at 7:53
  • So how can I call a method from there? Commented Aug 21, 2016 at 7:54
  • 2
    This is invalid use of the class keyword. It would throw Uncaught SyntaxError: Unexpected token =. Did you mean to use var/let/const? Commented Aug 21, 2016 at 7:54
  • Also, methodTwo already has access to methodOne, they are defined in the same scope, so you can just call it directly methodOne(), there's no need for this.methodOne(). Additionally, you need to research how this gets bound in JS, depending on how a function is called, particularly when called as a constructor or an object method. Commented Aug 21, 2016 at 7:58

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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)
        });
    }
};

1 Comment

Yepp, it is not clear whether he wants to use ES5 or ES6, the syntax is half way between them. Since he is using DOM and there is no babel tag on the question I guess he is trying to work with ES5 in the browser.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.