是什么导致了这个意外的Javascript错误?

时间:2011-09-07 00:56:49

标签: javascript html css dom

此代码旨在为每个没有“ShowThis”类的元素或者该类的后代添加样式“display:none”:

var x = document.getElementsByTagName('*');
for(var i = x.length; i--;){
    x[i].style.display = 'none';
    if((' '+x[i].className+' ').indexOf(' ShowThis ') >= 0){
        var y = x[i];
        while(y){
            if(y.nodeType === 1){
                console.log(y.style.cssText);    // Outputs: "display: none;"
                console.log(y.style.display);    // Outputs: "none"
                y.style.display = 'block';
                console.log(y.style.display);    // Outputs: "block"
                console.log(y.style.cssText);    // Outputs: "display: block;"

                // ERROR here:
                    // Outputs the elements HTML (Chrome Console),
                    // But the style attribute isn't changed
                    // EX. <div style="display: none;">...</div>
                console.log(y);
            }
            y = y.parentNode;
        }
    }
}

这是一个JSFiddle:http://jsfiddle.net/Paulpro/wEq8X/

如果您注释掉if(y.nodeType === 1){和匹配的}http://jsfiddle.net/Paulpro/wEq8X/1/),或者我将if语句更改为if(y.nodeType)if(true),则可以正常工作这对我来说没有任何意义,因为程序流正在输入if语句(所有console.log都被执行)。

我已尝试将if语句更改为if(typeof y.style !== 'undefined'),但其行为也不正确。 (完全相同的问题)

我需要测试nodeType或样式以防止在尝试访问文档的样式属性时出错,但是测试其中任何一个都会给我带来这种奇怪的行为。

我可以在Chrome,Firefox和IE中重复此操作。

2 个答案:

答案 0 :(得分:2)

您的代码将包含块设置为“display:none”。在那之后,内部<div>是“display:block”无关紧要。

您倾倒元素的诊断技术存在缺陷。如果你使用Chrome调试器或Firebug之类的东西,你会发现你的“ShowThis”元素确实在其“style”属性中有“display:block”。但是,它没有显示,因为它的所有父元素(包括<body>标记)仍然是“display:none”。

编辑我认为问题可能源于页面元素在“getElementsByTagName()”结果中出现的顺序。如果在子元素之后到达父元素,那么它们将被设置为“display:none”之后它们被设置为“display:block”。

再次编辑 - 已确认。从“getElementsByTagName()”返回的元素以逆序的形式返回,它们出现在HTML中。因此,代码在外部循环中看到的最后一个元素是“ShowThis”<div>的容器<div>

再次编辑哦,我看到了 - 你要倒退!!杜尔。如果你继续通过节点列表,它应该工作。

答案 1 :(得分:1)

你问的是你的外部循环隐藏了所有东西,然后在你设置为display ='block'之后隐藏'showthis'节点的父节点。如果你将隐藏和显示分成两个步骤,它就可以正常工作。

var y, x = document.getElementsByTagName('*');
for(var i = 0, len = x.length; i < len; i++){
    x[i].style.display = 'none';
}
x = document.getElementsByClassName('ShowThis');
for(var i = 0, len = x.length; i < len; i++) {
    y = x[i];
    while(y){
        if(y.nodeType === 1){
            y.style.display = 'block';
        }
        y = y.parentNode;
    }
}

另外,只是为了记录,这种类型的东西是jQuery很棒的地方。

jQuery('*').hide();
jQuery('.ShowThis').show().parents().show();