Reputation: 945
I'm trying to write a basic function in order to produce a cash machine. Whenever I run the below code, I get the total staying at 0. Can anyone help me out or explain to me why?
function VirtualCashMachine(){
//object storing food
this.food = {egg: 0.98, milk: 1.23, magazine: 4.99,chocolate: 0.45};
//total bill
this.total = 0;
//record of last transaction
this.lastTransactionAmount = 0;
//assign public methods
this.scan = scan;
this.voidLastTransaction = voidLastTransaction;
//define public methods
//add amount to total property
function scan(/*string*/item,/*integer*/ quantity){
//if food item exists in food object, find price and calculate total
if(this.food.hasOwnProperty(item)){
cost = this.food[item] * quantity;
add(cost);
this.lastTransactionAmount = cost;
}
};
function voidLastTransaction(){
this.total -= lastTransactionAmount;
};
//define private method
//add item price to total
function add(itemCost){
this.total = this.total + itemCost;
};
}
var VCM = new VirtualCashMachine();
VCM.scan("egg", 3);
console.log(VCM.total);
The problem seems to arise when I implemented the add function. My reasoning is that once I find the total costs for 3 eggs in this example, I add the amount to the this.total
and can repeat this for other sorts of food.
Upvotes: 0
Views: 134
Reputation: 100547
"this" is often not what you think it is... I.e. when you call function without context (add
instead of VCM.scan
) the context will be set to global object. There are many articles on the subject - i.e. Understanding JavaScript Context.
There are several options to deal with it.
One is to call it with context by making it "public member" as suggested by tomca32 (Note that it will expose private methods which may not be desirable in many cases):
this.add = function(itemCost) { this.total += itemCost;} this.add(cost);
Another option is to save this
into local variable so you know what exactly you are using:
function VirtualCashMachine(){
var self = this;
....
function add(itemCost){
self.total = self.total + itemCost;
};
Or you can explicitly pass context with function.call
:
function add(itemCost) { this.total += itemCost;}
add.call(this, cost);
or you can avoid this
in local functions altogether, but you'll need to expose properties with get/set methods. In this case since function will sees all local variables in parent's scope it can correctly modify total:
var total = 0;
this.getTotal() { return total;}
function add(itemCost) { total += itemCost;}
Second approach (with copying this
to local variable) is quite common and easiest to follow in my opinion: simply use self
(or other commonly used me
or that
) everywhere inside your class where you would use this.
.
Upvotes: 3
Reputation: 1140
Re-write add to be a property of this:
this.add = function (itemCost) {
this.total = this.total + itemCost;
}
Upvotes: 3