0

I have this Car function:

var Car = function(vendor, model, year) {
    return {
        vendor: vendor,
        model: model,
        year: year,
        name: (function() {
            return vendor + " " + model + " " + year;
        })()
    };
};
var foo = Car("Toyota","Corola",2007);
alert(foo.name);  //alerts "Toyota Corola 2007"

This works, but I want the name to be able to change according to the vendor, model, and year.

taxi.vendor = "Mitsubishi";
alert(taxi.vendor); //still alerts "Toyota Corola 2007"

How can I instead make it alert Mitsubishi Corola 2007 according to the change of the vendor property?

EDIT: And the catch -- name must remain a property that does not need to be called as a function.

Peter Olson
  • 139,199
  • 49
  • 202
  • 242
  • I'm in trouble, I didn't check the prior posts! [Prior Cool Discussion][1] [1]: http://stackoverflow.com/questions/6349121/choosing-an-oop-pattern-in-javascript – Don Henton Sep 27 '11 at 17:06

3 Answers3

4

With recent versions of WebKit (Safari, Chrome) or Firefox, you can define getter and setter functions:

var o = {a: 7, get b() {return this.a + 1;}, set c(x) {this.a = x / 2}};
o.b // result is 8
o.a = 10
o.b // result is 11

Then you would do this:

var Car = function(vendor, model, year) {
    return {
        vendor: vendor,
        model: model,
        year: year,
        get name() { return this.vendor + " " + this.model + " " + this.year; }
    };
};

And get the result that you want.

I don't know if IE or Opera support this or which versions. If you need to support anything other than recent Safari, Chrome, or Firefox browsers then you're better off using a function to access the name instead of leaving it as a property:

var Car = function(vendor, model, year) {
    return {
        vendor: vendor,
        model: model,
        year: year,
        name: function() { return this.vendor + " " + this.model + " " + this.year; }
    };
};

And then:

var foo = Car("Toyota","Corola",2007);
alert(foo.name());  //alerts "Toyota Corola 2007"
foo.vendor = "Mitsubishi";
alert(foo.name());  //alerts "Mitsubishi Corola 2007"
mu is too short
  • 426,620
  • 70
  • 833
  • 800
2

How about:

 var Car = function(thevendor, themodel, theyear) {
    this.vendor = thevendor;
    this.model = themodel,
    this.year = theyear,
    this.name = function() {
            return this.vendor + " " + this.model + " " + this.year;
        };
    return this;
};


var foo = new Car("Toyota","Corola",2007);
alert(foo.name());  //alerts "Toyota Corola 2007"

foo.vendor = "Mitubishi";
alert(foo.name());  //alerts "Mistubishi Corola 2007"

JSFiddle for this code: http://jsfiddle.net/duncan_m/gZKQD/

Duncan_m
  • 2,526
  • 2
  • 21
  • 19
2

When you use name: (function() {return vendor + " " + model + " " + year;})(), that means that the name property will be set to the result of executing this function. This happens when you create a new Car. But it sounds like you want this to update dynamically, so consider having name be a getter function instead of just a string property:

name: function() {return vendor + " " + model + " " + year;}

Then you can do alert(taxi.name()), which will dynamically concatenate the vendor, model, and year strings.

jtbandes
  • 115,675
  • 35
  • 233
  • 266
  • Is it possible without making `name` a function? – Peter Olson Jun 20 '11 at 17:39
  • If you want to do it without making `name` a function, you would have to make setter functions (e.g. `setVendor`, `setModel`, and `setYear`) so that each time something changes you could recreate the `name`. You can also use [getters and setters](https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Working_with_Objects#Defining_Getters_and_Setters) as another commenter mentioned. – jtbandes Jun 21 '11 at 06:13