JavaScript Jems - Objects with Values
Written by Ian Elliot   
Thursday, 23 May 2019
Article Index
JavaScript Jems - Objects with Values
toString
Using factory objects and constructors
Functions v Objects

An object factory

Of course usually you need multiple copies of the item object and the simplest way of achieving this is to use an object factory:

var CItem = function(name, tax, price){
var item = {};
item.name = name;
item.tax = tax;
item.price = price;
item.valueOf = function(){
return item.price;
};
item.toString = function(){
return item.name;
};
return item;
}

Now we can define multiple item objects and use them with default values as before:

var item1 = CItem("widget1", 0.1, 10);
var item2 = CItem("widget2", 0.1, 20);
alert(item1);
alert(item2);

As the alert expects a string parameter the result is widget1 followed by widget2.

Now what do you think is displayed by:

alert(item1+item2);

As + is the arithmetic addition operator the result is 30 i.e. the valueOf method is called on each object given the result numeric 30 which is then converted to a string.

Using a constructor

If you want to create lots and lots of item objects then you really need to use a constructor and implement the methods using the prototype property. Notice that the only real reason for doing this is efficiency. If you use the object factory approach then each object has a complete copy of the valueOf and toString methods but if you use a constructor then the same prototype methods are shared by all the item objects.

The usual rule for converting a factory function into a constructor is to replace the name of the object that is being created by this:

var CItem = function(name, tax, price){
this.name = name;
this.tax = tax;
this.price = price;
this.valueOf = function(){
return this.price;
};
this.toString = function(){
return this.name;
};
}

Now the only difference is that you have to use new in front of the creation of any objects:

var item1 = new CItem("widget1", 0.1, 10);
var item2 = new CItem("widget2", 0.1, 20);
alert(item1);

Of course you can also use new in front of a factory function but it isn't made use of and it makes no real difference.

Prototype

To make each item object more efficient by sharing a single copy of the valueOf and toString functions between all of the instances we simply need to define them as methods of the CItem functions prototype object:

var CItem = function(name, tax, price){
this.name = name;
this.tax = tax;
this.price = price;
}
CItem.prototype.valueOf = function(){
return this.price;
};
CItem.prototype.toString = function(){
return this.name;
};

With this change the two methods are now shared by all the instances of Item. However they work in exactly the same way and

var item1 = new CItem("widget1", 0.1, 10);
alert(item1);

still displays widget1.

In case you are wondering why examples of valueOf and toString were given for a singleton, factory function and constructor the reason is that mostly the documentation only shows the two methods defined using the prototype object. This sometimes results in the mistaken idea that the prototype object is somehow involved in the default value mechanism. It isn't and the rule is that if an object has a valueOf method then it is used when the object is being treated like a number of a Boolean and if the object has a toString method it is used when the object is being treated like a string.

Functions

Now we come to a tricky area. In JavaScript functions are objects - yes they can have properties and methods. They can therefore have toString and valueOf methods. What this means is that a function can return three different values depending on how it is used.

Consider:

function myFunction() {
 return 1;
};
myFunction.valueOf = function() { return 2; }; myFunction.toString = function() { return "A"; };

After this what does:

alert(myFunction);

display? Answer: "A".

What does

alert(myFunction+0);

display?  Answer: 2.

Finally, what does:

alert(myFunction());

display? Answer: 1.

This also raises the issue of why bother using a function if general objects can return a value?

The reason is fairly obvious but deserves some thought.

JavaScriptJems



Last Updated ( Tuesday, 06 August 2019 )