views:

540

answers:

7

I'm just starting to get my mind around this whole Object Oriented thing, so bear with me.

So, I saw an example of an object function (for Javascript) where you assign a new value and that value gets assigned as that property's actual value. Example:

function Meat (name, color, price) {
    function newPrice (new_price) {
        this.price = new_price;
    }
 this.name = name;
 this.color = color;
 this.price = price;
 this.newprice = newPrice;
 }

Fine and dandy. Now I have the ability to assign a price by using Bacon.price or Bacon.newprice. Personally, this seems like the highest order of semantics, since functionally it does the same thing. But as an advocate for semantic coding, I'll let it slide. Here's what I want:

When I change the value of Bacon.price, the object should include a function to store the old value in a property called oldprice automatically. I played around with this, but got nowhere. Here's what I've tried so far:

function Meat (name, color, price) {
    function oldPrice () {
        this.oldprice = this.price;
    }
 this.name = name;
 this.color = color;
 this.oldprice = oldPrice;
 this.price = price;
 }

///////////////////////

function Meat (name, color, price) {
    this.name = name;
    this.color = color;
    this.oldprice = this.price;
    this.price = price;
}

More or less variations of that. I thought that referring to the already assigned value (which would be nothing the first time) before the new value got assigned would be enough. I know that the value (or lack thereof) is stored somewhere before it gets assigned, I just don't know how to refer to it to assign it to the oldvalue property before it gets wiped out.


Okay, maybe the problem is with my eyes or fingers then. Because I thought I had tried the suggestions before asking (I know, I didn't mention them!) Unless I'm really confused, this should work:

function Meat(price)
{

    function setPrice(price)
    {
        this.oldprice = this.price;
        this.price = price;
    }

this.price=setPrice;
}

bacon = new Meat()
bacon.price = "Expensive";
document.write(bacon.price+"<br />");
document.write(bacon.oldprice+"<br />");
bacon.price = "Cheap";
document.write(bacon.price+"<br />");
document.write(bacon.oldprice+"<br />");

But the output I get is: Expenisive undefined Cheap undefined

All okay until that last one. Again, I am willing to accept bad eyesight and poor spelling as the root. But I can't figure it out.

+2  A: 

This will store it when you call obj.newPrice(xxx); - I don't think you can do it automatically when using obj.price = xxx;

function Meat (name, color, price) {
    function newPrice (new_price) {
        this.oldprice = this.price
        this.price = new_price;
    }
 this.name = name;
 this.color = color;
 this.price = price;
 this.newprice = newPrice;
 }

Edit:

As noted by @Mauris, Javascript 1.5 does support getters and setters (see also here - you can think of them as methods disguised as properties.

Using these, your code would look like this:

function Meat (name, color, price) {
    function newPrice (new_price) {
        this.oldprice = this.price
        this.price = new_price;
    }
 this.name = name;
 this.color = color;

 this.__defineSetter__("price", function(newprice)
 {
       this.oldprice = this.price
       this.price = price;
 });
 }

Unfortunately this syntax isn't supported by Internet Explorer yet.

Greg
You can using __defineSetter__. More info here: http://ejohn.org/blog/javascript-getters-and-setters/
Marius
@Marius Sure, but only if you're using jQuery. If it's straight JS OOP code than you can't do that.
leeand00
+1  A: 

Is that it?

function setPrice(price) {
  this.oldprice = this.price;
  this.price = price;
}
cherouvim
A: 

Consider what you are trying to do:
1. Remember the old price
2. Change the current price to a new one

Since these are the two steps of what you want to do, you need to stick them in the one function. You will need to first remember what the current price is (in this.oldprice), and then change the current price (this.price). The responses from RoBorg and cherouvim have the code to do this.

Smashery
A: 

Um first-off I'm not so sure that you're doing OOP Javascript correctly. OOP Javascript isn't actual Object oriented programming to begin with, and it works off of something called a prototype instead:

For instance:

function Meat (name, color, price) {
       if(arguments.length > 0) 
 {
   this.init(name, color, price);
 }
}

Meat.prototype.init = function(name, color, price) {
 this.name = name;
 this.color = color;
 this.price = price;

 // Initially these are all set to null, 
 // because they don't have an old value yet.
 this.old_name = null;
 this.old_color = null;
 this.old_price = null;
};

And that would make up your constructor.

Next we need to add some methods so that your old values can be stored:

Meat.prototype.setName = function(new_name) {
 // Store the old name of the meat
 this.old_name = this.name;
 this.name = new_name;
};

And you'd write a method like this for every property in your meat.

leeand00
At least in pure Javascript OOP with a base level class, this is how it would work.
leeand00
A: 

since you are just starting out with OO javascript, hear out this advice:

dont use the new keyword to create objects. use functional inheritance instead. This way you can easily get private variables, and i think the syntax is much easier. check it out:

var meat = function(name, color, price){
   var that = {};
   var name = name;
   var price = price;
   var color = color;
   var oldPrice = null;
   var setPrice = function(p){
      oldPrice = price;
      price = p;
   };
   var getPrice = function(){ return price;};
   var getOldPrice = function(){return oldPrice;};
   that.getPrice = getPrice;
   that.setPrice = setPrice;
   that.getOldPrice = getOldPrice;
   return that;
};

you can use the above like this:

var m = meat("chicken", "white", 100);
m.setPrice(50);
var old = m.getOldPrice();

now you might need getName and setName method etc. if you want inheritance, you can do something like this:

var cow = function(name){
    var that = meat(name, "spotted", 100);
    that.moo = function() { return name +" moooo"; };
    return that;
}

anyway, i may have answered the wrong question, but maybe you will read this and see the light :)

mkoryak
The point of functional inheritance is not to simulate private variables, it's to avoid loosing your scoping of `this`.
Crescent Fresh
thank god you are still answering my questions. oh wait... but actaully, good point. i should have mentioned that too =).
mkoryak
A: 

there's no getter/setters or operator overloading in JS (yet) so you really do need to write a function to set the price and get those fun side-effects.

Scott Evernden
A: 

You're overwriting your price variable. Don't forget that in javascript, you can assign anything to a variable, since it's not strongly typed. So, The way you have it set up:

function Meat(price)
{

    function setPrice(price)
    {
        this.oldprice = this.price;
        this.price = price;
    }

this.price=setPrice; //<-- this assigns the function "setPrice" to the variable "this.price"
}

bacon = new Meat()
bacon.price = "Expensive"; //<-- this overwrites the "price" variable with a string
document.write(bacon.price+"<br />");
document.write(bacon.oldprice+"<br />");
bacon.price = "Cheap";
document.write(bacon.price+"<br />");
document.write(bacon.oldprice+"<br />");

You can (as mentioned) use getters and setters, assuming you don't need IE support. Otherwise, use the method you defined:

bacon = new Meat();
bacon.setPrice("Expensive");
document.write(bacon.price+"<br />");
document.write(bacon.oldprice+"<br />");
bacon.setPrice("Cheap");
document.write(bacon.price+"<br />");
document.write(bacon.oldprice+"<br />");

Since you really want to force access to those values, I'd write getters for them as well:

bacon.getPrice();
bacon.getOldPrice();
jvenema