调试技巧
在开发过程中,我们可能会遇到报错,脚本无法正常运行,或者运行结果和预期不一致。这时候我们需要进行调试,找出问题所在,并修复问题。本章将介绍一些调试的基本技巧。
删除可能出错的脚本
当遇到报错时,首先要找到出错的位置。尝试删除一行或多行可能出错的代码,然后重新执行程序,观察是否依然有报错。通过这种方法逐步缩小错误代码的范围,直到定位到具体出错的代码。
将可能出错的代码行前增加
//
,表示这段代码为注释,不会被执行。例如:
// 物品.金钱 = 物品.金钱 * 2
打印变量
当我们发现程序中某个属性值或临时变量不符合预期时,可以通过使用
提示
打印变量,跟踪变量在执行过程中的变化,从而确定是否是中间过程出现了问题。例如:
将
属性.签到次数
打印出来,帮助我们观察中间过程中签到次数的变化,判断是否存在问题:for (var i = 0; i < 10; i = i + 2) {
属性.签到次数 = 属性.签到次数 + 1;
提示(属性.签到次数); // 发送提示,内容是当前签到次数的值
}
读取数据库的值,然后打印出来,从而调试数据库是否按照预期进行工作:
数据.写(['成员', 玩家.id, '金钱'], 100)
var 金钱数值 = 数据.读(['成员', 玩家.id, '金钱'])
提示(金钱数值); // 发送提示,内容是数据库中的值
直接打印一个文本,判断该条件分支是否被执行到:
if (xxx) {
xxxx;
if (xxx) {
xxxx;
return;
} else {
提示('此处被执行了') // 发送提示,说明这里被执行过
}
}
录制日志
通过录制日志,可以直接查看每一条命令所传入的参数。
如上图所示,每行第一个值为该命令的名称,跟在后面的为相关的参数(例如,属性名、要写入的值、数据库路径等)。
从日志中,可以查看代码的运行过程是否符合预期。
逐步执行
逐步执行代码可以帮助我们找到出错的具体位置。一个一个地执行可能出错的代码段,检查每一段代码执行后的对变量和属性的影响。一旦发现问题,就修复它,确保每一步都符合预期。
步骤1;
// 步骤2;
// 步骤3;
// 步骤1;
步骤2;
// 步骤3;
// 步骤1;
// 步骤2;
步骤3;
常见情况
如果进行了简单的调试,代码却依然没有按照预期工作时,往往是以下几种可能:
代码功能和预期不符
某段代码的作用和想象的不一样。
例如,下面这段代码错误的判断了签到次数是否等于1、2、3:
if (属性.签到次数 === 1 || 2 || 3) {
// 相当于 属性.签到次数 === 1 || true || true,条件始终成立
// 因此,if 里面的代码将始终被执行
}
遇到这种情况,应当逐步执行代码,检查代码执行过程中的临时变量,找到开始不符合预期的位置。
输入值超出预期
来自属性或数据库的值可能超出预期。例如,玩家输入的数字有可能是负数,数据库的值有可能是undefined。
例如,下面这段代码读取玩家所在公会的人数,并增加人数。
var 人数 = 数据.读(['公会', 属性.公会名称, '人数']); // 公会数据可能不存在,读取的数值为 undefined
人数++; // undefined + 1 会变成 NaN
数据.写(['公会', 属性.公会名称, '人数'], 人数); // 最终写回数据库的值就变成了 NaN,导致报错
遇到这种情况,应当使用
提示
检查每条命令所使用的值是否符合预期。其它因素
- 某段代码没有被执行(检查 if 条件)
- 某段代码意外被执行(检查 if 条件、延迟执行和活跃动作)
- 错打了某个符号,导致语义发生变化(处理办法与“代码功能和预期不符”类似)
开发时的注意事项
如果我们想开发一个复杂的功能时,需要理清整体流程,思考代码会怎么运行,有哪些步骤和分支,要存储哪些数据,用户要怎么操作。
如果不确定功能是否能按照预期想法工作,可以将其拆分成一些简单的逻辑进行开发。每开发完一个简单功能,验证它是否可以按照预期工作。
当不熟练如何开发时,尽量避免根据“直觉”和“感觉”进行功能设计和开发,而是使用纸笔对运行过程进行演算,搞明白功能细节如何运作,数据是如何发生变化的。
坚定信念
在调试代码时,需要不断缩小错误范围,增加“我确定这段代码是正确的”的比例,避免因盲目尝试而原地踏步。
代码始终会按照命令进行执行,如果没有按照预期工作,那么肯定是由某个确定的因素导致的。要相信,只要思路正确,代码一定可以被修复并成功运行。