Een classe laat buiten het toekennen van properties (waardes) ook nog het implementeren van functies toe.
Hierdoor kan er zeer krachtige code geschreven worden en kom je in het object georienteerd programmeren terecht.
Dit voorbeeld laat zien dat we een classe kunnen definiëren waarin 3 functies gebruikt worden.
/**
* Class of 1d array of scores from quizzes
* @param {array} arr, array of scores
*/
class Quizscore {
constructor(arr) {
this.arr = arr
}
max() {
Logger.log(this.arr)
//calculate Max value per Coursework array
let max = 0
for (let i = 0; i < this.arr.length; i++) {
if (this.arr[i] > max) {
max = this.arr[i]
}
}
return max
}
length() {
return this.arr.length
}
sum() {
let sum = 0
for (let i = 0; i < this.arr.length; i++) {
sum += this.arr[i]
}
return sum
}
avg() {
let avg = 0
let cnt = 0
for (let i = 0; i < this.arr.length; i++) {
cnt++
avg = parseInt((avg + this.arr[i]) / cnt)
}
return avg
}
}
Binnen een classe kan je ook recursive code gebruiken, waardoor de classe vanin de classe terug wordt aangeroepen.
let subgrade = new Grade(this.obj[keys[o]])
Doordat bij iedere aanroep een nieuwe omgeving wordt gemaakt op de stack, kan je recursief bepaalde bewerkingen doen.
Het gebruik van recursieve code vereis dat je in je constructie één of meerdere finale uitkomst acties hebt en één of meerdere accties die zichzelf terug aanroepen.
Het voorbeeld wat je hier ziet loopt door een boomstructuur van objecten, waarbij het laagste niveau bestaat uit een array, waarvan steeds de maximale waarde wordt bepaald.
Deze structuur is opgezet om een rapport te genereren, waarbij ieder object een totaal kan vormen van alle subobjecten.
Dit is dus de recursieve noodzaak.
De structuur kan een 1 of meerdere niveau's diep zijn.
Het object wat de array's bevat kan een aggregaat maken van de uitslagen als een max of een gemiddelde waarde (finale uitkomst)
Welke functie moet worden toegepast, wordt bepaald door de "opcode"
Wanneer dit niet bereikt wordt, zal de code zichzelf terug aanroepen (recursie) door het volgende stukje code:
let subgrade = new Grade(this.obj[keys[o]]
Hierdoor wordt een nieuwe omgeving gevormd, waarbinnen de voorgaande werking opnieuw wordt bekeken.
Onderstaand codevoorbeeld geeft het gebruik binnen een raport generator.
let REP = [[]]
REP.shift()
REP.push(["Titel","Omschrijving","Grade"])
let items = Object.keys(itemlink)
for (let k = 0; k < items.length; k++) {
//Logger.log(items[k])
let gr = new Grade(itemlink[items[k]])
itemlink[items[k]].grade = gr.grade()
REP.push([items[k], template.Omschrijving[k],itemlink[items[k]].grade])
}
De bovenstaande functie is de aanroep ervan en zoals je ziet is er enkel een toekenning van de uitkomst aan een variabele
let gr = new Grade(itemlink[items[k]])
waarna de waarde eenvoudig kan afgevraagd worden met de functie
gr.grade()
De structuur onderaan laat je zien hoe deze complexe waarde dient berekend te worden.
/**
* class Grade
* @param {object} obj
* method: grade()
* If obj=array, calculate max value of elements
* if obj= obj -> drill down to subobject array
*/
class Grade {
constructor(obj) {
this.obj = obj
}
grade() {
let prop = this.obj.constructor
if (prop.name == "Array") {
let max = 0
for (let i = 0; i < this.obj.length; i++) {
if (this.obj[i] > max) {
max = this.obj[i]
}
}
return max
} else if (prop.name == "Object") {
//opcode default action
if (this.obj.opcode == "avg" || !this.obj.opcode) {
let avg = 0
let cnt = 0
let keys = Object.keys(this.obj)
for (let o = 0; o < keys.length; o++) {
Logger.log(o)
//recursive call
if (keys[o] != "opcode") {
let subgrade = new Grade(this.obj[keys[o]])
Logger.log(subgrade)
if (subgrade.grade()) {
avg += subgrade.grade()
cnt++
}
}
}
Logger.log(`avg: ${parseInt(avg / cnt)}`)
let avgval = parseInt(avg / cnt)
if (isNaN(avgval)) {
// twee opeenvolgende lege niveau's
avgval = `#Error`
}
return avgval
} else
if (this.obj.opcode == "max") {
let avg = 0
let keys = Object.keys(this.obj)
for (let o = 0; o < keys.length; o++) {
Logger.log(o)
if (keys[o] != "opcode") {
//recursive call
let subgrade = new Grade(this.obj[keys[o]])
Logger.log(subgrade)
if (subgrade.grade() > avg) {
avg = subgrade.grade()
}
}
}
Logger.log(`maxagg:${avg}`)
return avg
}
}
}
}