资讯专栏INFORMATION COLUMN

一个递归函数的漏洞及优化

Riddler / 540人阅读

摘要:下面函数采用了递归如果文字超出宽度,在函数中将原字符截断末尾字符并加上再次调用判断是否超出宽度。直至获得宽度合适的字符串并输出。需要优化的递归函数超出宽度这样看起来没问题。其实需要优化很多地方。

现在有一个需求:

如果“一个字符串”超出“容器宽度”,将字符串截断最后一个字符、并在末尾加上‘...’ ,再次判断是否需要截断。直至字符串小于容器宽度。

下面SliceLabelStr函数采用了递归:
如果文字超出宽度,在attrStyle函数中将原字符截断末尾字符并加上‘...’ 再次调用sliceLabelStr判断是否超出宽度。
直至获得宽度合适的字符串并输出。

需要优化的递归函数
sliceLabelStr = function( textWidth, textStr) {
    var str;
   
    if(超出宽度) {
        dataLabel2 = attrStyle(textStr);
        var newTextWidth =  dataLabel2.text && dataLabel2.text.element.getBoundingClientRect().width;
        var textStr = dataLabel2.text.textStr;
        sliceLabelStr( newTextWidth, textStr);
    } else {
        str = attrStyle(textStr, true);
        return str; 
    }  
}

这样看起来没问题。其实需要优化很多地方。

1、递归没有出口

这个递归函数被调用了10遍,在11遍的时候符合了出口条件退出了,
那么在第10遍没退出的时候,1到10次的函数都没有退出,只有在第11遍符合了出口条件return了以后,就会从11~1倒着依次退出

附上一张太阳神手写的解释图

优化方法1
if(textWidth > containerWidth) {
        dataLabel2 = attrStyle(textStr);
        var newTextWidth =  dataLabel2.text && dataLabel2.text.element.getBoundingClientRect().width;
        var textStr = dataLabel2.text.textStr;
        return sliceLabelStr( newTextWidth, textStr);//有返回值
    } 

1、上述原因是递归没有出口,而且if语句中调用本函数递归的时候没有返回值。

2、有时会产生“调用栈溢出”的情况。

2、在if判断条件中,由于在某种情况下textWidth没有变化造成了无限递归

3、用do...while 代替 递归

sliceLabelStr = function(forX2Array, textWidth, textStr) {
    var str,
        sliceStr = textStr.text && textStr.text.textStr || textStr;

    if(compareTextLength(forX2Array, textWidth)) {
        var n=0;

        do{
            n++;
        }
        while(sliceStr.substr(0,n)!=sliceStr && attrLabel2Style(forX2Array[0], sliceStr.substr(0,n)).getBBox()["width"]

逻辑比较直观,简单能用循环的就用循环,递归一般用在复杂算法,比如弗洛伊德,A+之类

4、这是SVGElement,如果是普通的DOM元素。可以用如下方法。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/81474.html

相关文章

  • 什么是编程基本功?

    摘要:正是前人的努力,我们现在的编程才会如此的容易。读懂他人代码算法如果别人是大牛,数学学得很好,很多数学公式,很多递归,如果自己没有一定的数学基础,可能就晕了,这个时候,数学的基本功可能就会在这里发挥作用了。 作者:caoglish原文链接:http://t.cn/RKcyGX3来源:知乎 查询和阅读文档能力 原因:你使用编程来解决问题的时候,基本上最终的东西是代码,但是编程的知识太广,总...

    Acceml 评论0 收藏0
  • 什么是编程基本功?

    摘要:正是前人的努力,我们现在的编程才会如此的容易。读懂他人代码算法如果别人是大牛,数学学得很好,很多数学公式,很多递归,如果自己没有一定的数学基础,可能就晕了,这个时候,数学的基本功可能就会在这里发挥作用了。 作者:caoglish原文链接:http://t.cn/RKcyGX3来源:知乎 查询和阅读文档能力 原因:你使用编程来解决问题的时候,基本上最终的东西是代码,但是编程的知识太广,总...

    lansheng228 评论0 收藏0
  • 什么是编程基本功?

    摘要:正是前人的努力,我们现在的编程才会如此的容易。读懂他人代码算法如果别人是大牛,数学学得很好,很多数学公式,很多递归,如果自己没有一定的数学基础,可能就晕了,这个时候,数学的基本功可能就会在这里发挥作用了。 作者:caoglish原文链接:http://t.cn/RKcyGX3来源:知乎 查询和阅读文档能力 原因:你使用编程来解决问题的时候,基本上最终的东西是代码,但是编程的知识太广,总...

    bbbbbb 评论0 收藏0
  • 什么是编程基本功?

    摘要:正是前人的努力,我们现在的编程才会如此的容易。读懂他人代码算法如果别人是大牛,数学学得很好,很多数学公式,很多递归,如果自己没有一定的数学基础,可能就晕了,这个时候,数学的基本功可能就会在这里发挥作用了。 作者:caoglish原文链接:http://t.cn/RKcyGX3来源:知乎 查询和阅读文档能力 原因:你使用编程来解决问题的时候,基本上最终的东西是代码,但是编程的知识太广,总...

    william 评论0 收藏0
  • [PHP] – 性能优化 – Fcgi进程PHP解析优化(1)

    摘要:是否启用安全模式。提示此参数已经没有了关闭危险函数如果打开了安全模式,那么函数禁止是不需要的,但是我们为了安全考虑还是设置。 1、PHP引擎缓存加速常见四种软件:1.eAccelerator2.Zendcache3.xcache4.apc5.zendopcache php5.5自带2、使用tmpfs作为缓存加速缓存的文件目录[root@web02 ~]# mount -t tmpfs ...

    zhaot 评论0 收藏0

发表评论

0条评论

Riddler

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<