Javascript 说我的类方法不是函数,尽管它显然是

标签 javascript node.js

我正在尝试使用 Node 实现遗传算法,我查看了此处发布的其他问题,它似乎不相关。当我尝试调用determine_fitness时我的方法populant类我收到此错误:

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)

我对 javascript 很陌生,所以我不知道除了跟踪堆栈跟踪之外还能做什么,但它没有给我任何答案。

但是,当我查看我的类(class)时:

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;
    }
}

正如你所看到的,它在这里定义得非常清楚,而且它与我的任何其他属性名称都不冲突,所以我真的很困惑。

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;
    }
}

我现在组织类(class)的方式是 populant类和 population类在自己的文件中 ga.js然后我将它们导入到我的 test.js 中文件。因为determine_fitness()方法populant默认情况下未定义,我创建了一个子类并覆盖它,如下所示:

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;
    }
}

然后我正在测试如图所示的结构:

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);
}

哪里print_pops()只是打印出 genes每个居民都拥有自己的属性(property)。

最佳答案

您可以尝试在尝试调用 certain_fitness 之前通过记录 p 的类型来检查 p 的类型是否是您所期望的:

fitness() {
    for(let p in this.pop) {
        console.log(typeof p);
        p.determine_fitness();
    }    
}

另外,由于 pop 是一个列表,我认为您将一个对象推送到它,您可以使用 for ... of 语法:

fitness() {
    for (p of this.pop) {
        p.determine_fitness();
    }
}

来自MDN article on for ... in :

Given that for...in is built for iterating object properties, not recommended for use with arrays, and options like Array.prototype.forEach() and for...of exist, what might be the use of for...in at all? [Emphasis mine]

关于Javascript 说我的类方法不是函数,尽管它显然是,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58669793/

相关文章:

javascript - 如何给表单动态添加 "hidden"字段?

javascript - 从悬停到单击的下拉标题

javascript - JavaScript 中的保留函数名称

javascript - jqGrid 鼠标拖动调整大小

node.js - 将 pdf url 传递给查询字符串中的 pdf.js

node.js - 如何更新 mongodb 上其他数组中数组的值?

javascript - 你能将图像与位置 :relative with an image that has position:absolute? 对齐吗

javascript - 将表单序列化为不带空值的 json

javascript - Socket.io socket.handshake 在断开连接时未定义

javascript - Express.js (node.js) 中的 require 和导出混淆