【问题标题】:Inconsistent Javascript behaviour (IF statement nested in while loop)不一致的 Javascript 行为(嵌套在 while 循环中的 IF 语句)
【发布时间】:2011-09-09 10:03:43
【问题描述】:

我正在尝试编写一个简单的 Javascript(jQuery) 函数,该函数随机显示可能的 11 个 Div 中的 6 个。代码排序工作,它确实随机显示大约一半的 Div,但它在4和8。

谁能告诉我哪里出错了?看起来应该很简单,但我完全迷路了!

我的代码:

<div class="offer">Offer 1</div>
<div class="offer">Offer 2</div>
... snip
<div class="offer">Offer 11</div>

<script src="query.min.js" type="text/javascript"></script>


 <script>
            var changed = 0;

            while (changed < 6) {


                $('.offer').each(function(index) {

                    if (changed < 6) {

                        var showOrNot = Math.floor(Math.random() * 2);

                        if (showOrNot == 1) {

                            $(this).addClass('offershow');
                            changed += 1;
                            $(this).text(changed); //debugging looking for the current value of changed 
                        }


                    }


                })


            }

        </script>

【问题讨论】:

  • 当我测试它时效果很好 - jsfiddle.net/infernalbadger/LX5xC 它偶尔会小于 6,因为没有检查以确保它不会两次更改同一个 div。
  • 你为什么要输出div,这不应该是服务器端/数据库的工作吗?
  • 啊,是我没有考虑到的。谢谢!认为卢克可能是正确的,但是更“精确”的解决方案可能会更好。
  • ps Val:我更喜欢在服务器端做这个——而且我的技能确实更适合这个——但是唉......政治。

标签: javascript jquery random while-loop


【解决方案1】:

目前的问题是你有一堆不相关的尝试。如果你有一个有 11 个球的桶,并且有 50% 的机会取出每个球,你最终可能会得到介于 0 到 11 之间的任意数量的球。概率偏向中心,但你没有得到 6 个,而恰好是 6 个每次。

你想要的是删除六个,正好六个,任意选择的球。

试试这样的:

var offers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
for (var i = 0; i < 6; i += 1) {
    // choose a remaining offer at random
    var index = Math.floor(Math.random() * offers.length);

    // retrieve the item being shown
    var item = $('.offer').eq(offers[index]);
    item.addClass('offerShow');

    // remove this offer from the list of possibilities
    offers.splice(index, 1);
}

编辑:在 cmets 中,OP 澄清说他真正想要的是采用任意大小的报价列表并显示其中的六个。下面提供的代码解决了需要,而不是原始问题中的严格要求。我将保留原始代码以供参考。

var OFFERS_TO_SHOW = 6;  // config, of sorts

// make sure no offers are shown now
$('.offer').removeClass('offerShow');

// show offers selected at random
for (var i = 0; i < OFFERS_TO_SHOW; i += 1) {
    // get a list of offers not already being shown
    var candidates = $('.offer').not('.offerShow');

    // select one from this list at random
    var index = Math.floor(Math.random() * offers.length);

    // show this offer by adding the offerShow class
    candidates.eq(index).addClass('.offerShow');
}

【讨论】:

  • 在 cmets 中,我看到很多关于这段代码运行之前的初始状态的讨论。我不认为这是您问题的症结所在,但是您可以轻松地设置初始状态,只需从一开始就从所有报价中删除该类:$('.offer').removeClass('offerShow');
  • 我认为这肯定是要走的路。不太确定如何使用 jQuery 来实现它,但我相信我会找到一种方法。谢谢!
  • 今晚晚些时候将阅读并回复您的评论。再次感谢!
  • 为什么你需要 jQuery 的 each?
  • @Jack 你将无法使用each(),因为这只是为了运行序列的次数与你拥有的元素一样多,而不是你需要的那么多。您可以使用$('.offer').length 获取您的集合长度,并使用$('.offer')[i] 直接访问元素。
【解决方案2】:

我认为问题在于您没有排除已设置显示的 div。因此,您选择下一个要显示的 div 的代码可能是选择了一个已经显示的。如果这有意义吗?尝试更改您的选择器.....

$('.offer').not('.offershow').each(........

请记住,addClass 不会删除现有的类,因此即使您添加了 offershow 类,您的原始选择器仍然会被证明是正确的。

【讨论】:

  • 谢谢你——这就是我想要的。卢克确实在评论中首先到达那里,因此接受了答案......
  • 不用担心,他肯定给出了更详细的答复和答案,您可以选择任何一种方式。 :) 感谢您的评论!
【解决方案3】:

您实际上并没有检查所选 div 是否已显示。意味着当您遍历所有 div 时,总是有可能将 div 设置为可见两次。脚本现在认为它是一个新的并设置更改 += 1;

尝试添加如下内容:

if(!$(this).hasClass('offershow')) {
    [[rest of code here]]
}

【讨论】:

    猜你喜欢
    • 2017-02-06
    • 1970-01-01
    • 2016-10-30
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-12
    相关资源
    最近更新 更多