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

JavaScript类实例跨文件使用全局变量时出现未定义错误的问题排查

解决ES模块中类无法访问测试文件全局变量的问题

问题根源

你的GuessingGame类依赖了全局变量number,但ES模块有独立的作用域:

  • 当你在类所在文件里定义var number时,这个变量属于该模块的作用域,类的方法自然能访问到;
  • 测试文件里的const number是挂在测试环境的global对象上的,但ES模块内部的代码默认不会去global查找变量,所以会抛出ReferenceError。

最优解决方案:封装目标数字为类实例属性(推荐)

依赖全局变量是不良实践,会导致代码耦合性高、可测试性差。更好的做法是把要猜的数字作为类的实例属性,让每个游戏实例拥有自己的目标数字,符合面向对象的封装原则。

修改后的类代码:

export class GuessingGame {
  constructor(targetNumber) {
    this.targetNumber = targetNumber; // 把目标数字存入实例
    this.min = null;
    this.max = null;
  }

  setRange(min, max) {
    this.min = min;
    this.max = max;
  }

  guess() {
    if (this.min + 1 === this.targetNumber) {
      return this.min + 1;
    } else if (this.max - 1 === this.targetNumber) {
      return this.max - 1;
    } else {
      return Math.round((this.max - this.min) / 2 + this.min);
    }
  }

  lower() {
    const currentGuess = this.guess();
    if (currentGuess > this.targetNumber) {
      this.max = currentGuess;
    }
  }

  greater() {
    const currentGuess = this.guess();
    if (currentGuess < this.targetNumber) {
      this.min = currentGuess;
    }
  }
}

对应的测试文件修改:

it('should guess number 409 with max value 4048', () => {
  const targetNumber = 409;
  // 实例化时传入目标数字
  const game = new GuessingGame(targetNumber);
  game.setRange(0, 4048);
  
  // 后续测试步骤保持不变...
  
  expect(result).to.equal(targetNumber);
});

备选方案:显式访问全局对象(不推荐)

如果你一定要保留全局变量的方式(不建议),可以在类的方法里显式引用global对象(仅适用于Node.js环境,浏览器环境需换成window):

// 修改类的guess方法
guess() {
  if(this.min + 1 === global.number) {
    return this.min + 1;
  } else if(this.max - 1 === global.number) {
    return this.max - 1;
  } else {
    return Math.round((this.max - this.min) / 2 + this.min);
  }
}

// lower和greater方法同理,替换number为global.number

这个方案的缺点是代码和环境强绑定,无法跨平台运行,且全局变量会让代码难以维护和调试。

内容的提问来源于stack exchange,提问作者Valentín_Lu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 18:42:39