考虑以下代码块,重复运行(jsFiddle):
var length = 50,
xOffset = 0,
yOffset = 0;
for (var a = 0; a < 100; ++a) { // just so we can see it "break"
for (var l = 1; l <= length; l++) {
var percentComplete = l / length,
scaledPercent = (.5 - Math.abs(percentComplete - .5)) * 2,
shake = 0,
shakeTries = 0,
deviationCeil = Math.ceil(10 * scaledPercent);
if (Math.random() < .1 || Math.abs(xOffset) > deviationCeil)
do {
shake = Math.floor(Math.random() * 3) - 1;
if (++shakeTries > 100) throw "X shake exceeded"
}
while (Math.abs(xOffset + shake) > deviationCeil);
xOffset += shake;
shakeTries = 0; // if we set shake = 0 here, everything works!
if (Math.random() < .1 || Math.abs(yOffset) > deviationCeil)
do {
shake = Math.floor(Math.random() * 3) - 1;
if (++shakeTries > 100) throw "Y shake exceeded"
}
while (Math.abs(yOffset + shake) > deviationCeil);
yOffset += shake;
}
}
反复运行时,抛出“Y shake exceeded”异常(不会抛出“超出X抖动”)。
解决方法是在Y块之前将shake
设置为0:shake = shakeTries = 0
。
我不明白为什么会这样。在这两个块中,我们首先分配摇动,所以在进入shake
块之前,真正的地狱do
是什么并不重要。我对do...while
的理解(以及我使用它的原因)是它在测试条件之前首先执行它的块。
那么,为什么我在shake
阻止之前没有重置do
时会失败(不是每次都失败)?
答案 0 :(得分:3)
如果我们添加一些额外的{
和}
,这种奇怪的行为会变得更加明显。让我们先看一下X部分。在开始时,shake和shakeOffset都等于0。
if (Math.random() < .1 || Math.abs(xOffset) > deviationCeil) {
do {
shake = Math.floor(Math.random() * 3) - 1;
if (++shakeTries > 100) throw "X shake exceeded"
} while (Math.abs(xOffset + shake) > deviationCeil);
}
xOffset += shake;
此时,shake具有上一个块(-1,0或1)中最后使用的值。然后我们到达Y部分:
shakeTries = 0; // if we set shake = 0 here, everything works!
if (Math.random() < .1 || Math.abs(yOffset) > deviationCeil) {
do {
shake = Math.floor(Math.random() * 3) - 1;
if (++shakeTries > 100) throw "Y shake exceeded"
} while (Math.abs(yOffset + shake) > deviationCeil);
}
yOffset += shake;
如果我们不满足(Math.random() < .1 || Math.abs(yOffset) > deviationCeil)
的条件,那么我们完全跳过do...while
并将抖动的值从X部分添加到yOffset。