You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用原型方法初始化JS对象,Mocha测试遇Score非构造函数错误求解决

解决"Score不是构造函数"错误并优化计分类结构

咱们先从最直接的报错问题入手,再一步步优化你的类结构来实现「接收掷骰结果和计分规则计算得分」的目标。


第一步:修复"Score不是构造函数"的报错

这个问题完全是模块导入导出不匹配导致的:
你的源码里是通过module.exports.Score = Score把构造函数挂载到导出对象的Score属性上,但测试代码里直接把整个模块赋值给了Score变量——相当于你在尝试new一个普通对象,而不是构造函数本身。

修正导入方式即可:

// 方式1:解构导入(推荐,更清晰)
const { Score } = require('../src/Score.js');

// 方式2:直接取导出对象的属性
var Score = require('../src/Score.js').Score;

第二步:修复Score类本身的基础问题

你的类目前还有两个明显的逻辑漏洞:

1. 构造函数未正确接收roll参数

现在的构造函数里硬编码了this.roll = [],完全忽略了传入的掷骰结果,改成下面这样才能正确存储传入的roll:

var Score = function (roll, category) {
  this.roll = roll || []; // 传入roll就用传入的,空数组兜底避免报错
  this.category = category;
};

2. ones方法未返回计算结果

当前的ones方法里,filter+reduce的计算结果没有被return,调用后会得到undefined。另外给reduce加初始值0,可以避免空数组时抛出错误:

Score.prototype.ones = function() {
  return this.roll.filter((i) => i == 1)
                  .reduce((sum, i) => sum + i, 0);
};

第三步:优化类结构实现「动态计分规则」的目标

你的核心需求是让Score类根据传入的计分规则计算得分,这里提供两种实用方案:

方案1:通过方法名指定预设计分规则

适合有固定计分规则集合的场景,比如骰子游戏的标准计分项(ones、twos、full house等):

var Score = function (roll, category) {
  this.roll = roll || [];
  this.category = category; // 传入预设的方法名,比如'ones'
};

// 通用得分计算方法,自动调用对应规则
Score.prototype.calculateScore = function() {
  if (typeof this[this.category] === 'function') {
    return this[this.category]();
  }
  throw new Error(`找不到对应计分规则:${this.category}`);
};

// 预设各类计分规则
Score.prototype.ones = function() {
  return this.roll.filter(i => i === 1).reduce((sum, i) => sum + i, 0);
};

Score.prototype.twos = function() {
  return this.roll.filter(i => i === 2).reduce((sum, i) => sum + i, 0);
};

// 可以继续扩展其他规则,比如fullHouse、yahtzee等
module.exports.Score = Score;

对应的测试代码示例:

const { expect } = require('chai');
const { Score } = require('../src/Score.js');

describe('Score', function() {
  describe('基础实例化', function() {
    it('应该是Score的实例', function() {
      const score = new Score([1,2,3,4,5], 'ones');
      expect(score).to.be.an.instanceOf(Score);
    });
  });

  describe('计分规则测试', function() {
    describe('ones规则', function() {
      it('应该计算所有1的总和', function() {
        const score = new Score([1,1,2,3,5], 'ones');
        expect(score.ones()).to.equal(2);
        expect(score.calculateScore()).to.equal(2); // 测试通用计算方法
      });
      it('没有1时应该返回0', function() {
        const score = new Score([2,3,4,5,6], 'ones');
        expect(score.calculateScore()).to.equal(0);
      });
    });
  });
});

方案2:直接传入自定义计分函数

适合需要动态定义特殊计分规则的场景,灵活性更高:

var Score = function (roll, scoringFn) {
  this.roll = roll || [];
  this.scoringFn = scoringFn; // 直接传入自定义函数
};

Score.prototype.calculateScore = function() {
  if (typeof this.scoringFn === 'function') {
    return this.scoringFn(this.roll);
  }
  throw new Error('传入的计分规则不是有效函数');
};

// 依然可以保留预设规则方便复用
Score.prototype.ones = function() {
  return this.roll.filter(i => i === 1).reduce((sum, i) => sum + i, 0);
};

module.exports.Score = Score;

自定义规则的测试示例:

describe('自定义计分规则', function() {
  it('应该使用自定义函数计算得分', function() {
    // 自定义规则:计算所有偶数的总和
    const evenSumFn = (roll) => roll.filter(i => i % 2 === 0).reduce((sum, i) => sum + i, 0);
    const score = new Score([1,2,3,4,5], evenSumFn);
    expect(score.calculateScore()).to.equal(6); // 2+4=6
  });
});

最后提一句:你原来测试代码里的new Score([1,2,3,4,5], this.ones)是错误的——this.ones在describe回调里是undefined,要改成对应方案的参数(比如方案1的'ones',方案2的Score.prototype.ones或自定义函数)。

内容的提问来源于stack exchange,提问作者Karl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:26:55