I'm working on a complex Javascript application which includes its own data structure. The previous version's data structure was rather chaotic, and I'm looking to replace it with something where:
- Every data item is an object which is (effectively) an instance of a class, which imposes a common structure including default values
- Where possible, functions which set or get the data in a data item are taken out of the controller logic and attached to the data item class prototype
The problem I'm trying to solve by introducing this structure is, lots of messy and inconsistent 'model' style logic buried deep in 'controller' style functions, which has led to inconsistency, type errors, missing data errors, duplicated logic, etc.
Here's an example which uses the exact same approach I'm taking to defining and accessing instances (but the contents of data structure itself is simplified, since my question is about the way it's defined and accessed). I know that Javascript doesn't exactly have object 'classes' the way other languages do, and I've read about approximating them using prototypes, but I may be doing it wrong. In particular:
- Do I need an
init()
function? Seems fine without one. - Is this a robust approach to the instance object accessing its own data? Can I rely on
this
within the attached function always being the instance's own data each time the function is called? Or should I be prepared to usecall()
or wrap calls in an anonymous function, or set it as a variable likethat
orself
? - Is this a good way to give a class of objects default values? Note that this application already uses jQuery for other non-negotiable reasons, hence
$.extend
, and namespacing is already covered - I put the
defaults
object in the prototype so it's not redefined each time a new instance is created. Am I right in thinking this is a better practice than defining it within the function? - My actual application isn't about currencies, so please don't comment on the business logic. The code for setting the class is taken straight from my actual application draft, but I did swap the actual parameters and functions with simpler examples (if I hadn't, the explanation of the parameters and purpose of the functions would be longer than the rest of this question combined, and I'd need tonnes of non-relevant code to give a working example)
var dataItem = function(values){
// Initiate new instance
$.extend(this,this.defaults,values);
};
dataItem.prototype.defaults = {
// Structure & defaults for each data item
value: 0.0,
currency: 'USD'
};
dataItem.prototype.formatCurrency = function(){
// Simple example of a 'getter' function
var formatted = '';
switch(this.currency) {
case 'GBP':
formatted = '£';
break;
case 'USD':
case 'CAD':
case 'AUD':
formatted = '$';
break;
}
return formatted+this.value.toFixed(2)+' '+this.currency;
};
// Some simple usage examples
var expenses = new dataItem({
value: 199.5,
currency: 'GBP'
});
var canadaIncome = new dataItem({
currency: 'CAD'
})
var taxes = new dataItem({
value: 60
})
document.write( expenses.formatCurrency() + ' : ' + canadaIncome.formatCurrency() + ' : ' + taxes.formatCurrency() );
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>