IE只有getElementsByTagName的javascript错误

时间:2010-01-27 00:54:15

标签: javascript internet-explorer

我有以下代码,可在FF / Chrome中使用

var stack = [Array.prototype.slice.call(document.getElementsByTagName("body")[0].childNodes)], nodes, node, parent, text, offset;
while (stack.length) {
    nodes = stack.pop();
    for (var i=0, n=nodes.length; i<n; ++i) {
        node = nodes[i];
        switch (node.nodeType) {
            case Node.ELEMENT_NODE:
                if (node.nodeName.toUpperCase() !== "SCRIPT") {
                    stack.push(Array.prototype.slice.call(node.childNodes));
                }
                break;
            case Node.TEXT_NODE:
                text = node.nodeValue;
                offset = text.indexOf("[test=");
                if (offset >= 0 && text.substr(offset).match(/^(\[test=(\d+)\])/)) {
                    parent = node.parentNode;
                    var before = document.createTextNode(text.substr(0, offset));
                        link = document.createElement("a"),
                        after = document.createTextNode(text.substr(offset + RegExp.$1.length));
                    link.appendChild(document.createTextNode(text.substr(offset, RegExp.$1.length)));
                    link.setAttribute("href", "http://example.com/" + RegExp.$2);
                    parent.insertBefore(after, node);
                    parent.insertBefore(link, after);
                    parent.insertBefore(before, link);
                    parent.removeChild(node);
                    stack.push([after]);
                }
        }
    }
}

基本上它的作用是如果它在页面中找到[test = 25]它将其转换为指向example.com/25的链接

在IE中,我收到以下错误:第一行预期的JScript对象:

var stack = [Array.prototype.slice.call(document.getElementsByTagName("body")[0].childNodes)], nodes, node, parent, text, offset;

IE7和IE8都会出现此错误。

任何帮助都将不胜感激。

感谢。

3 个答案:

答案 0 :(得分:12)

Array.prototype.slice属性(或其他各种DOM方法)返回的NodeList对象上调用childNodes是不合法的。

通常,Thing.prototype.methodThing的实例之外的任何内容都是合法的,但传统上允许浏览器 - 而ECMAScript第三版标准要求 - 许多{{{ 1}}方法,以便可以在任何类似于Array.prototype的本机JavaScript对象上调用它们。这意味着,它们可以在Array对象上使用,它看起来像arguments但实际上不是。{/ p>

但是,Array和DOM中的其他集合对象未定义为本机JavaScript对象;它们被允许成为“主机对象”,它们完全由浏览器而不是语言实现。所有投注都是关闭主机对象......

  

切片功能是否可以成功应用于主机对象是依赖于实现的。

所以NodeList可能不适用于NodeList,而在版本8之前的IE中,实际上它不会。

如果你想制作一个NodeList的普通数组副本,你将不得不采用漫长但安全的方式:

Array.prototype.slice

顺便说一句,你可以使用Array.fromSequence= function(seq) { var arr= new Array(seq.length); for (var i= seq.length; i-->0;) if (i in seq) arr[i]= seq[i]; return arr; }; var stack = [Array.fromSequence(document.body.childNodes)]; 使链接器更简单一些,并且我对使用全局textnode.splitText属性非常谨慎,就像任何一个意外的正则表达式工作一样。干预电话他们会丢失。查看匹配对象通常更好。请参阅this question以了解基本相同问题的其他攻击。

答案 1 :(得分:3)

我认为这是因为getElementsByTagname返回一个节点列表 - 而不是一个数组(虽然像[]运算符这样的东西就像它们在数组上工作一样,它们不一样)

也许它可以用一种不太复杂的方式解决:

var els = document.body.getElementsByTagName("*");
for (var i=0, numEls=els.length, el; i<numEls; i++){
    el = els.item(i);
    el.normalize();        
    for (var j=0, chs = el.childNodes, numChs=chs.length, ch; j<numChs; j++){
        ch = chs.item(j);
        if (ch.nodeType==Node.TEXT_NODE){
          //you code for replacing text with link goes here
          //ps i suggest using  ch.data instead of ch.nodeValue
        }
    }
}

答案 2 :(得分:2)

请尝试使用此代码:

var stack = [Array().slice.call(document.getElementsByTagName("body")[0].childNodes)]

IE和原型/构造函数有一些时髦性。 我现在无法在Mac上进行测试。

此处有更多信息:Difference between Array.slice and Array().slice