I'm trying to implement a genetic algorithm using node and I looked at the other question posted here, and it seems unrelated.  When I try to call the determine_fitness method of my populant class I get this error:
Creating new population
Starting iteration 1
/home/aaron/Documents/workspace/playground/screeps_ga/ga.js:116
            p.determine_fitness();
              ^
TypeError: p.determine_fitness is not a function
    at population.fitness (/home/aaron/Documents/workspace/playground/screeps_ga/ga.js:116:15)
    at population.train (/home/aaron/Documents/workspace/playground/screeps_ga/ga.js:130:18)
I'm really new to javascript, so I'm not sure what to do here besides just follow the stacktrace and it's not giving me any answers.
But, when I look at my classes:
class populant {
    constructor(genes) {
        this.genes = genes;
        this.score = -1;
    }
    mutate() {
        if(this.genes.length == 0)
            this.genes += random_char();
        else {
            let r = getRndInteger(0, 3);
            let i = getRndInteger(0, this.genes.length);
            switch(r) {
                case 0:
                    // Remove a character
                    let before = this.genes.substring(0, i);
                    let after = this.genes.substring(i + 1);
                    this.genes = before + after;
                    break;
                case 1:
                    // Replace a character
                    let c = random_char();
                    let before = this.genes.substring(0, i);
                    let after = this.genes.substring(i + 1);
                    this.genes = before + c + after;
                    break;
                case 2:
                    // Add a character
                    let c = random_char();
                    let before = this.genes.substring(0, i);
                    let after = this.genes.substring(i);
                    this.genes = before + c + after;
                    break;
            }
        }
    }
    mate(other, mutate) {
        let i = 0;
        let temp = '';
        for(i = 0; i < this.genes.length; i++)
        {
            if(getRndInteger(0, 2) == 0)
                temp += other.genes.substring(i, i + 1);
            else
                temp += this.genes.substring(i, i + 1);
        }
        this.genes = temp;
        if(mutate)
            this.mutate();
    }
    determine_fitness() {
        return null;
    }
}
As you can see, it's very clearly defined here, and it doesn't conflict with any of my other property names, so I'm really confused.
class population {
    constructor(count, mutation_rate, populant_type) {
        this.count = count;
        this.mutation_rate = mutation_rate;
        this.populant = populant_type;
        this.pop = [];
    }
    initialize(parent_pool) {
        this.pop = [];
        if(parent_pool.length == 0)
            for(let i = 0; i < this.count; i++)
                this.pop.push(new this.populant(random_gene()));
        else if(parent_pool.length == 1)
            for(let i = 0; i < this.count; i++)
                this.pop.push(new this.populant(parent_pool[0].genes));
        else
        {
            for(let i = 0; i < this.count; i++)
            {
                let pai = getRndInteger(0, parent_pool.length);
                let pbi = getRndInteger(0, parent_pool.length);
                let temp_pa = new this.populant(parent_pool[pai].genes);
                let should_mute = Math.random() < this.mutation_rate;
                temp_pa.mate(parent_pool[pbi], should_mute);
                this.pop.push(temp_pa);
            }
        }
    }
    fitness() {
        for(let p in this.pop)
            p.determine_fitness();
    }
    select_parents(count) {
        this.pop.sort(function(a, b){ return a.score - b.score; });
        return this.pop.slice(0, count);
    }
    train(iterations, crossover_size, initial_parents) {
        let selected_parents = initial_parents;
        for(let i = 0; i < iterations; i++)
        {
            this.initialize(selected_parents);
            this.fitness();
            selected_parents = this.select_parents(crossover_size);
        }
        return selected_parents;
    }
}
The way that I have the classes organized right now is that the populant class and the population class are in their own file ga.js and then I import them into my test.js file. Because the determine_fitness() method of populant isn't defined by default, I created a child class and overwrote it as seen below:
let ga = require('./ga');
class StringPop extends ga.populant {
    constructor(genes) {
        super(genes);
    }
    determine_fitness() {
        let sum = 0;
        for(let i = 0; i < this.genes.length; i++)
            sum += this.genes.charCodeAt(i);
        this.score = sum;
        return sum;
    }
}
And then I'm testing the structure as shown:
pop = new ga.population(20, 0.25, StringPop);
let iteration = 1;
let parents = []
while(true)
{
    console.log('\nStarting iteration ' + iteration.toString());
    parents = pop.train(1, 5, parents);
    console.log('Population after iteration');
    print_pops(pop);
}
Where print_pops() just prints out the genes property of each populant on their own line.
 
    