使用setInterval调用Car类方法返回NaN,直接调用正常的技术问题
问题分析与解决方案
核心问题
- 变量作用域导致实例覆盖:循环中用
var声明usrAuto和inter,var是函数级作用域,三次循环后所有定时器都会指向最后创建的usrAuto实例,且inter变量会被后续循环覆盖,导致无法正确清除对应定时器。 - NaN问题来源:
parseInt未处理输入非数字的情况,若用户输入无效值,speed或maxSpeed会变成NaN,后续速度相加时自然得到NaN;另外作用域问题导致调用drive时可能访问到错误的实例属性。
修正后的代码
//require "prompt-sync" const prompt = require("prompt-sync")({ sigint: true }); //Auto class class Car{ constructor(brand, speed, maxSpeed, currentSpeed){ this.carBrand = brand; // 处理NaN,确保速度为有效数字 this.carSpeed = typeof speed === 'number' && !isNaN(speed) ? speed : 0; this.carMaxSpeed = typeof maxSpeed === 'number' && !isNaN(maxSpeed) ? maxSpeed : 0; this.carCurrentSpeed = currentSpeed; // 存储定时器ID,方便实例自身清除 this.intervalId = null; } drive(){ if(this.carCurrentSpeed >= this.carMaxSpeed){ clearInterval(this.intervalId); console.log(`${this.carBrand} 已达最大速度,停止加速`); }else{ this.carCurrentSpeed += this.carSpeed; console.log(`${this.carBrand} 当前速度:${this.carCurrentSpeed} km/h`); } } } //gameloop for(let i = 0; i < 3; i++){ //infos from usr let brand = prompt("请输入汽车品牌:"); // 处理输入,确保得到有效数字,第二个参数是进制,避免意外 let speed = parseInt(prompt("请输入每秒加速值:"), 10) || 0; let maxSpeed = parseInt(prompt("请输入汽车最大速度:"), 10) || 0; //create Object let usrAuto = new Car(brand, speed, maxSpeed, 0); // 把定时器ID绑定到实例上,方便drive方法清除 usrAuto.intervalId = setInterval(() => { usrAuto.drive(); }, 1000); }
关键修改点
- 把循环中的
var替换为let,利用块级作用域保证每次循环的usrAuto和定时器都是独立的。 - 给
Car类添加intervalId属性,让实例自身管理定时器,避免外部变量作用域问题。 - 对
parseInt的结果做默认值处理,防止输入非数字导致NaN;同时在构造函数中再次校验速度值,确保属性为有效数字。 - 使用箭头函数作为
setInterval的回调,自动绑定当前的usrAuto上下文,无需手动调用call。
内容的提问来源于stack exchange,提问作者asgr
相关产品推荐
相关产品推荐

