0

I have a basic lack in understanding the OOP for javascript. What I understand is that I can make classes like this

var Car = function(){}

Car.prototype.GetBrand = function(){ return "Ford";}
Car.prototype.GetYear = function(){ return "1989";}

var ford = new Car();

ford.GetBrand();
ford.GetYear();

this works... Now I want to implement a function GetInfo and this should print out Brand & Date

how can I reference the GetBrand() and GetYear() methods in my GetInfo() method.

  This is not working:
Car.prototype.GetInfo = function(){ 
        return this.GetBrand()+ ' '+ this.GetYear();
    }

this is not the right accessor... What do I miss here?

OK edit: this was a simplified example there my realy method call is in anothe function and that's why we are talking about another scope:

JsonLoader.prototype.GetJsonAndMerge = function(url,template,tagToAppend){
$.ajax({
    url: url,
    dataType: 'json',
    success: function(data) {
        this.ShowItems(data,template,tagToAppend); 
        }
    });
}

I try to reach my ShowItems method... here and this is again in a function that's maybe why the this operator does not work... sorry for the confusion =/

3
  • well what is your ShowItems method actually part of? and why are you trying to reach it with this? Commented May 28, 2011 at 13:58
  • Wowzers. That's a completely different issue. A good lesson in why you should test your reduced test cases to make sure they still show the same problem (with the same error messages). Commented May 28, 2011 at 14:01
  • @Thomas Shields: ShowItems is also (or should be) a member method of JsonLoader,... JsonLoader.prototype.ShowItems(data, template, tagToAppend) Commented May 28, 2011 at 14:05

4 Answers 4

2

You are missing an unintended recursion:

Car.prototype.GetInfo = function (){  
  return this.GetBrand()+ ' '+ this.GetYear(); // instead of GetInfo() !
}

Then you can call

ford.GetInfo() // returns "Ford 1989"

EDIT: The reason to use prototype here is to conserve memory. When you call new Car(), the object gets copied, not "constructed" in the traditional sense. Calling new on

var Car = function(){
  this.GetBrand = function(){ return "Ford";}
  this.GetYear = function(){ return "1989";}
}

would also copy the function bodies to every instance. This is why putting a method into the prototype chain makes sense. Also adding a function to already-existing instances only works when adding it to the prototype chain.

Also note that the convention is to give capital first letters to constructor functions only, so Car is okay, but GetInfo should be getInfo.


JsonLoader.prototype.GetJsonAndMerge = function(url,template,tagToAppend){
  var self = this;
  $.ajax({
    url: url,
    dataType: 'json',
    success: function(data) {
      self.ShowItems(data,template,tagToAppend); 
      }
    });
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the reply. I might have another scope issue... I edited the question. I was hitting submit to early...
@serverinfo: Yes, see my second edit. The meaning of this changes from context to context. If you want to preserve a certain meaning across calls, you must store the current this in a temporary variable.
@serverinfo: Never mind! :) Explanation: When the Ajax success callback is invoked, it is done without any context. this is always the object a function is invoked on (this is why function.call() and function.apply() can work in the first place) - and the callback function is invoked on no particular object. Hence, this is the global (window) object for the callback, which does not know about ShowItems(). The contents of self (and that of the arguments) is preserved through the closure that you create here.
1

You're calling GetInfo from inside its definition; naturally that's not going to work:

Car.prototype.GetInfo = function(){ 
        return this.GetBrand()+ ' '+ this.GetInfo(); //note GetInfo here
    }

I believe you want:

Car.prototype.GetInfo = function(){ 
            return this.GetBrand()+ ' '+ this.GetYear(); //note GetYear here
        }

...then just call it with ford.GetInfo()

Comments

0

You are calling GetInfo recursively.

You probably mean:

return this.GetBrand()+ ' '+ this.GetYear();
//                                   ^^^^

Which works fine.

Comments

0

this is context sensitive to how the function it is in is called.

You are trying to use this from when foo.GetJsonAndMerge is called, but you aren't using it in GetJsonAndMerge. You are using it in an anonymous function which is called by $.ajax.

You need to make a copy of the current value of this in a variable that will remain available to the anonymous function when it gets called.

JsonLoader.prototype.GetJsonAndMerge = function(url,template,tagToAppend){
    var that = this; // COPY THIS
    $.ajax({
        url: url,
        dataType: 'json',
        success: function(data) {
            // USE THE COPY YOU PLACED IN THAT INSTEAD OF THIS
            that.ShowItems(data,template,tagToAppend); 
        }
    });
}

Comments

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.