【问题标题】:JS JQuery Highlight Plugin toUpperCase not a function, causes infinite loopJS JQuery Highlight Plugin toUpperCase不是函数,导致无限循环
【发布时间】:2011-10-04 22:19:55
【问题描述】:

我正在尝试编辑 jQuery 高亮插件以突出显示多个单词。在你按下空格键之前它工作得很好,然后它会导致 FF 在无限循环中冻结。

FireBug 报告说 .toUpperCase 不是一个函数,但是当我将相同的代码改回来时,它并没有改变数组元素,这很好,但没有突出显示这两个词,只有第一个词。当按下空格键时,所有突出显示都会消失。

这是我目前所拥有的。有问题的代码在最后的 return this.each(function(){}) 块中:

jQuery.fn.highlight = function(pat) {
function innerHighlight(node, pat) {
    var skip = 0;

    if (node.nodeType == 3) {
        var pos = node.data.toUpperCase().indexOf(pat);
        if (pos >= 0) {
            var spannode = document.createElement('span');
            spannode.className = 'highlight';
            var middlebit = node.splitText(pos);
            var endbit = middlebit.splitText(pat.length);
            var middleclone = middlebit.cloneNode(true);
            spannode.appendChild(middleclone);
            middlebit.parentNode.replaceChild(spannode, middlebit);
            skip = 1;
        }
    } else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
        for (var i = 0; i < node.childNodes.length; ++i) {
            i += innerHighlight(node.childNodes[i], pat);
        }
    }

    return skip;    
}
return this.each(function() {
    var parts = pat.split(' ');
    console.log(parts);
    for (var i in parts) {
        innerHighlight(this, parts[i].toUpperCase());
        console.log("parts["+i+"] >> " + parts[i]);
    }
});
};

这是 FireBug 中的控制台输出:

["guy"]                            jquery...ht-3.js (line 46)
parts[0] >> guy                    jquery...ht-3.js (line 49)
parts[i].toUpperCase is not a function
    [Break On This Error] innerHighlight(this, parts[i].toUpperCase());
                                   jquery...ht-3.js (line 48)

任何帮助将不胜感激!

【问题讨论】:

  • 我建议使用 CSS text-transform: uppercase; 而不是实际将字符串转换为大写。
  • 它在 JS 中转换的唯一原因是比较要突出显示的字符串。用户看到的文本永远不会改变。

标签: javascript jquery plugins highlight


【解决方案1】:

哦,亲爱的。该插件使用未经过滤的for...in 循环来迭代数组。 That's bad:

for...in 不应该用于遍历索引所在的数组 顺序很重要。数组索引只是可枚举的属性 整数名称,其他方面与一般对象相同 特性。不保证for...in 将返回 以任何特定顺序索引,它将返回所有可枚举的 属性,包括具有非整数名称的属性和 继承。

因为迭代的顺序是依赖于实现的,迭代 在一个数组上可能不会以一致的顺序访问元素。所以 迭代时最好使用带有数字索引的for 循环 访问顺序很重要的数组。

如果只应考虑对象的属性,则 应执行hasOwnProperty 检查以确保只有 使用对象的属性而不是继承的属性 (propertyIsEnumerable也可以使用,但不直观)。


所以,改变这个:

for (var i in parts) {
    innerHighlight(this, parts[i].toUpperCase());
    console.log("parts["+i+"] >> " + parts[i]);
}

到这里:

for (var i=0; i<parts.length; i++) {
    innerHighlight(this, parts[i].toUpperCase());
    console.log("parts["+i+"] >> " + parts[i]);
}

【讨论】:

  • 是的,我第一次尝试这种类型的 for,谷歌结果说它相当于 php 的 for..each,除非我读错了。改成其他类型,还是会导致FF挂掉。
  • 它还抱怨“.toUpperCase()不是一个函数吗?”如果是这样,当时parts[i] 的价值是多少? (切换console.loginnerHighlight函数调用的顺序看看。)
  • 不,这摆脱了 toUpperCase 问题。现在,它只是挂起,但正在超时。前后值相同。
  • 只有当空格是字符串的最后一个字符时才会挂起。它挂起大约 10-15 秒,然后提示结束脚本。 (.=空格)所以foo。挂起,但在它“克服它”之后 foo.bar .. 工作正常。当对话框出现时,它说 else if 块中的 for(var i=0; i
  • 我想我解决了。我最终在将字符串发送到 innerHighlight 方法之前对其进行了修剪,现在它似乎运行良好。
猜你喜欢
  • 2011-10-01
  • 1970-01-01
  • 2018-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多