1

I hate that I'm doing this but I've just started working with Javascript classes and I can't figure out how to call member functions from member functions. Below is the class I have and when I run this I get the following error in Firefox:

this.addCol is not a function

I've also tried calling the function like this:

Table.prototype.addCol(this,key,value);

but that also didn't work. :-)

Table.prototype.addCol = function(key, values){
    this.jquery.children('.columns').append('<li>' + key + '</li>');
}

Table.prototype.setData = function(data){
    // store the data for this table
    this.data = data;

    $.each(data.columns, function(key, value){
        this.addCol(key, value);
    });
}

function Table (name){
    this.name = name;

    this.jquery = $('<div class="dbtable"><h3>' + this.name + '</h3></div>');
}
1
  • 1
    Your problem is that this doesn't refer to your Table object inside of that anonymous function. Use a normal for-loop and it will work. Commented Jan 26, 2012 at 1:36

2 Answers 2

5

JavaScript has prototypal inheritance, not classical inheritance. There are no "classes" in JS. Using the "new Foo()" syntax in JS just sucks. It wasn't built to support that style of coding well.

That being said, there is a major design flaw in which a nested function inside an object will rebind this to the global object. In this case, this gets re-bound to the item in the $.each iteration.

There is a common workaround:

Table.prototype.setData = function(data){
    var that = this;
    // store the data for this table
    this.data = data;

    $.each(data.columns, function(key, value){
        that.addCol(key, value);
    });
}
Sign up to request clarification or add additional context in comments.

7 Comments

Modifications to addCol? This change wouldn't fix the error message this.addCol is not a function
It's not a design flaw, that's how free functions work. In this case, it's also not JS that's setting the binding, it's $.each, which binds this to the elements of the collection being traversed (after wrapping primitive types in Objects). In any case, this solution is the simplest.
This is more of a problem of functional scope. :P
Douglas Crockford would disagree with you about the design flaw part, though he is a pretty harsh critic ;)
@AlienWebguy This works but I don't understand why (and I hate saying that). Can you point my in the direction of something that would explain this (I would even be willing to pay for a physical book :-)).
|
0

Why not define the class as

function Table (name){
    this.name = name;

    this.jquery = $('<div class="dbtable"><h3>' + this.name + '</h3></div>');

    this.addCol = function(key, values){
        this.jquery.children('.columns').append('<li>' + key + '</li>');
    }

    this.setData = function(data){
        // store the data for this table
        this.data = data;

        $.each(data.columns, function(key, value){
            this.addCol(key, value);
        });
    }
}

in the first place?

3 Comments

For one reason, it's more memory intensive to instantiate new objects from this constructor.
I would argue that getting the application to work should be priority #1, and then optimization can come second.
@AdamMihalcin True, but he has already written it that way, plus the problem is this pointing to the global object, not what you have described.

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.