I'm trying to get my head around object oriented programming, and I'm starting in JavaScript. I have put a working demo of my code on JSFiddle (here), but the class is below.
My main concerns are that as soon as the object is called with a constructor, all the properties are populated straight away (there are no methods). Should I have put some of the contructor code into methods?
function XEString(encryptedString) {
if (!XEString.test(encryptedString)) { //Throw exception if invalid XEcrypt string
throw new Error("Invalid XECrypt string");
} else {
this.encryptedString = encryptedString; //Save encrypted string to object
//Remove first "." char and put numbs into array, then convert numbs from strs to ints
this.encryptedNumbers = this.encryptedString.substring(1).split(".");
for (var i = 0; i < this.encryptedNumbers.length; i++) {
this.encryptedNumbers[i] = parseInt(this.encryptedNumbers[i], 10);
}
//Each char is calced from a group of 3 numbs
this.stringLength = this.encryptedNumbers.length / 3;
//Create array for encrypted chars, and obj to map encrypted char freq
this.encryptedChars = [];
this.encryptedCharFreq = {};
//Loop for each letter
for (var i = 0; i < this.stringLength; i++) {
//Add together each group of 3 numbs
var thisChar = 0;
for (var j = 0; j < 3; j++) {
thisChar += this.encryptedNumbers[3 * i + j];
}
this.encryptedChars[i] = thisChar; //Store encrypted char code in array
//Keep a record of how many times each encrypted char occurred
if (this.encryptedCharFreq[thisChar] == null) { //If this char has not been seen before
this.encryptedCharFreq[thisChar] = 1; //Set the occurrence in the obj map to 1
} else { //Otherwise
this.encryptedCharFreq[thisChar]++; //Increment the occurrence in the obj map
}
}
//Get highest char freq (mode)
this.highestFreq = 0;
for (var i in this.encryptedCharFreq) {
if (this.encryptedCharFreq[i] > this.highestFreq) {
this.highestFreq = this.encryptedCharFreq[i];
}
}
//Get all highest freq chars (modes) and add objs containing key, decrypted string and numb of unprintable chars
this.decryptedStrings = [];
for (var i in this.encryptedCharFreq) {
if (this.encryptedCharFreq[i] == this.highestFreq) {
var key = i - 32; //Space char is ASCII code 32
var decryptedString = "";
var unprintableChars = 0;
for (var j = 0; j < this.stringLength; j++) { //for every char add the decoded ascii char and check for unprintable char
var decryptedChar = this.encryptedChars[j] - key;
decryptedString += String.fromCharCode(decryptedChar);
if (decryptedChar < 32 || decryptedChar > 126) { //Printable ASCII char codes range from 32-126
unprintableChars++;
}
}
this.decryptedStrings.push({
'key': key,
'decryptedString': decryptedString,
'unprintablechars': unprintableChars
});
}
}
//Get least unprintable chars
this.leastUnprintableChars = Infinity;
for (i in this.decryptedStrings) {
if (this.decryptedStrings[i]['unprintablechars'] < this.leastUnprintableChars) {
this.leastUnprintableChars = this.decryptedStrings[i]['unprintablechars'];
}
}
//Get best decrypted string(s)
this.bestDecryptedStrings = [];
for (i in this.decryptedStrings) {
if (this.decryptedStrings[i]['unprintablechars'] == this.leastUnprintableChars) {
this.bestDecryptedStrings.push(this.decryptedStrings[i]);
}
}
}
}
//Function for testing valid XEcrypted string. returns true or false
XEString.test = function(encryptedString) {
return /^((\.-?\d+){3})+$/.test(encryptedString);
}