0

我有一个非常奇怪的错误,似乎是竞争条件使width();调用产生不同的结果。

调用后我有这个jQuery

this.after(
    "<div class='menuItemContainer'>" +
        "<div class='menuItemTitle'>" +
            $("option:selected", this).text() + "<span class='menuItemDownArrow'>&#9660;</span>" +
        "</div>" +
        "<div class='menuItemList'>" +
        selectionMarkup +
        "</div>" +
    "</div>"
);

我在其中将 html 插入 DOM。

接下来我需要知道一个元素与类的组合宽度,menuItemColums并使它们的父 div 具有该宽度。

此标记存在于变量 中selectionMarkup

为此,我执行以下操作:

var w = 0;
$(".menuItemColumn").each(function(){
    w += $(this).width();
    console.log($(this));
    console.log(w);
});
$(".menuItemList").css({
    width: w}
);

这在大约 70% 的情况下完全按预期工作,但有时我对某些元素的测量结果是错误的,或者至少可以肯定第一个元素有时是错误的。

奇怪的是对象似乎是正确的,它的属性是正确的宽度,但widht()分配给的给定w是不正确的:

在此处输入图像描述

该图像,只是为了澄清显示了日志记录的结​​果,w并且$(this)应该是相同的,因为$(this)的 width 属性似乎是正确的。

我一直在调试,发现了两件事导致人们相信这是竞争条件:

如果我再次执行我发布给你的最后一段代码,当错误被重现时,它会解决问题。

如果我进行以下调用,会给我不同的结果,一个不正确,另一个(第二个)正确:

console.log($(".menuItemColumn:first").width());
setTimeout(function(){console.log($(".menuItemColumn:first").width());},3000);

我的印象是代码的第二部分在第一部分完成之前不会执行,这里给出了什么?

注意:我不能 100% 确定比赛条件是我正在寻找的词,但我的想法仍然是这样。


更新:

作为@WereWolf-TheAlpha,控制台的输出看起来不像jquery对象,我现在无法重现它,我只得到这个:

在此处输入图像描述

无需更改任何代码。

4

1 回答 1

1

这里的问题是,当对象在检查器中折叠时,Chrome 检查器将提供对对象的引用。当您单击该箭头以展开对象时,其属性将变为真实。您可以运行它来查看它的发生:

var obj = {};
for (i=0; i<100; i++)
  obj['foo'+i] = i;
console.log(obj);
for (i=0; i<100; i++)
  obj['foo'+i] = 'gotcha';
console.log(obj);

现在,展开检查器中的第一个对象。明白了!

于 2014-04-24T20:54:39.797 回答