【问题标题】:Why is this while JavaScript loop infinite?为什么这是while JavaScript循环无限?
【发布时间】:2011-11-15 15:43:39
【问题描述】:

我讨厌这样做。这是结束一个大项目的一小部分,我的头脑很紧张......

这是代码。它检查元素是否溢出并调整字体大小。它应该调整它的大小,直到它不溢出。循环的条件似乎被忽略了,浏览器冻结了......我觉得我错过了 jQuery 如何在这里工作的关键。

$.fn.fontBefitting = function() {
    var _elm = $(this)[0];
    var _hasScrollBar = false; 
    while ((_elm.clientHeight < _elm.scrollHeight) || (_elm.clientWidth < _elm.scrollWidth)) {
        var fontSize = $(this).css('fontSize');
        fontSize = parseInt(fontSize.substring(0,fontSize.length-2))*0.95;
        $(this).css('fontSize',fontSize+'px');          
    }

}

提前致谢。

【问题讨论】:

  • 'while' 循环在哪里?
  • 没有while循环?这是矩阵吗?
  • 哎呀,我把它作为条件发布了。已编辑...
  • “我曾经这样做过”是指将我认为我应该能够解决的问题倾倒在社区上。这是我觉得我应该知道的问题之一。
  • @Eric:实际上是$(this)[0] !== this,因为当您尝试将 jQuery 对象发送到 $() 时,它不会将其双重包装,而是为您提供一个引用相同元素的新 jQuery 对象,所以$(this)[0] === this[0].

标签: javascript jquery loops while-loop


【解决方案1】:

变化:

 fontSize = parseInt(fontSize.substring(0,fontSize.length-2))*0.95;

到:

 fontSize = parseInt(fontSize.substring(0,fontSize.length-2))-1;

这是Working Demo。当字体大小达到 10 像素时,10*.95 为 9.5,浏览器将其四舍五入为 10 像素。因此无限循环。

【讨论】:

  • 你的比较是正确的。但是 9.5 的 fontSize 又回到了 10。
  • 没问题,我去过。看同一个代码太久,知道这是我看不到的东西。我无法相信那个人告诉你辞职。这不是很优雅。很高兴我能帮上忙。
  • 现在用this markup 试试看为什么@rpophessagr 的代码仍然不正确。比较一下my fixed versionhere
  • 当您整天坐在电脑对面时,您可能会忘记您看到的文字是由其他人撰写的。感谢您的帮助!
【解决方案2】:

您需要在调试器中单步执行您的代码,并实际检查您的条件值,以确保它们改变了您的预期。我的猜测是 _elm.clientHieght_elm.clientWidth 实际上并没有改变。

【讨论】:

  • 他们在改变,代码使用条件而不是循环。
【解决方案3】:
var fontSize = $(this).css('fontSize');
fontSize = parseInt(fontSize, ...

您从font-size 获得的单位不一定是 (a) 像素,也不一定是 (b) 您输入的单位。

没有指定使用什么单位来返回长度,但在许多浏览器中它目前是点。由于点比像素小,整数长度会更长,所以你可以很容易地永远保持*0.95ing它。

即使是像素,浏览器也可以将大小四舍五入到最接近的像素,使 95% 的大小在您读取时与 100% 的大小相同。或者你可以达到 minimum-font-size 设置,你将无法再减小它。

因此,不要在每一步都读取当前字体大小,而是将所需的像素大小保留在一个变量中,并每次都减小该变量。然后,如果您达到该变量值的预定下限,请放弃。

【讨论】:

  • "你从 font-size 得到的单位不一定是 (a) 像素,也不一定是 (b) 你输入的单位。"当我调试解决方案时,它以 px 为单位,即使字体设置为 100%。这会因站点而异吗?
【解决方案4】:

您可能会陷入无限循环,因为字体大小实际上并没有改变。例如。如果找到的字体大小为 10px,您将其更新为 9.5px,浏览器可能会将其四舍五入为 10px。在这种情况下,什么都不会改变,函数将永远运行。

【讨论】:

  • 感谢您的帮助,这就是答案。由于工作示例,@abstract 获得了绿色检查。
【解决方案5】:

当你这样做时,你遇到了一个不相关的问题

$('div').fontBefitting()

这将使第一个 div 中的文本适合它的框,然后使所有其他 div 的字体大小与第一个相同。这听起来不像是预期的行为。你会希望它能让每个 div 调整其文本的大小,并且只调整其文本。

您需要将代码更改为:

$.fn.fontBefitting = function() {
    /* $.fn.* runs on a jQuery object. Make sure to return it for chaining */
    return this.each(function() {
        var fontSize = parseInt($(this).css('fontSize'));
        while (this.clientHeight < this.scrollHeight ||
               this.clientWidth < this.scrollWidth) {
            fontSize--;
            $(this).css('fontSize', fontSize + 'px');          
        }
    });
}

【讨论】:

  • 为什么投反对票? OP 的代码对$.fn 的工作方式以及浏览器如何处理字体大小做出了错误的假设。
  • 感谢您的努力和优化,但我想您是因为您的措辞而被否决。我建议未来的编辑说:“这里有一些方法可以优化你的代码。”而不是:“你的代码写得不好。”我会很乐意使用你的代码来改进我的。谢谢
  • @rpophessagr:这不仅仅是优化,您的代码行为不正确 - 调用 $('div').fontBefitting() 会使第一个 div 中的文本适合它的框,并使所有其他 div 的字体大小相同作为第一个。可能不是预期的行为。
  • +1,这不仅优雅地解决了问题,还修复了提到的错误并进行了优化,除了在每次调用时创建一个新的匿名函数。
【解决方案6】:

您正在检查clientHeightclientWidth 是否小于scrollHeightscrollWidth,如果是,您是否正在减小字体大小?在这种情况下,它永远不会收敛。你想增加字体大小。

【讨论】:

  • 我正在减小字体大小,以免溢出。
猜你喜欢
  • 2012-05-02
  • 2012-11-01
  • 2018-03-17
  • 2016-07-14
  • 1970-01-01
  • 2016-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多