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

发布于 2024-12-03 04:27:59 字数 1659 浏览 0 评论 0原文

此代码旨在将样式“display: none”添加到不具有“ShowThis”类或具有该类的后代的每个元素:

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 或 style 以防止在尝试访问文档的 style 属性时出现错误,但是测试它们中的任何一个都会给我带来这种奇怪的行为。

我可以在 Chrome、Firefox 和 IE 中重现这一点。

This code is meant to add the style 'display: none' to every element which does not have the class 'ShowThis', or a descendant with that class:

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;
        }
    }
}

Here's a JSFiddle: http://jsfiddle.net/Paulpro/wEq8X/

It works fine if you comment out if(y.nodeType === 1){ and the matching } (http://jsfiddle.net/Paulpro/wEq8X/1/), or if I change the if statement to if(y.nodeType) or if(true) which doesn't make any sense at all to me, since the program flow is entering that if statement (all the console.log's are executed) anyways.

I've tried changing the if statement to if(typeof y.style !== 'undefined') and it behaves incorrectly as well. (Exactly the same problem)

I need to test nodeType or style to prevent the error when it tries to access the document's style property, but testing either of them gives me this weird behaviour.

I can repro this in Chrome, Firefox, and IE.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

网名女生简单气质 2024-12-10 04:28:00

您的代码将包含块设置为“display: none”。之后,内部的

是“display: block”就没关系了。

你们倾倒元素的诊断技术是有缺陷的。如果您使用 Chrome 调试器或 Firebug 等工具,您会看到“ShowThis”元素的“style”属性中确实有“display: block”。但是,它不会显示,因为它的所有父元素(包括 标记)仍然是“display: none”。

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

再次编辑 - 已确认。从“getElementsByTagName()”返回的元素以它们在 HTML 中出现的相反顺序出现。因此,您的代码在循环中看到的最后一个元素是“ShowThis”

的容器

再次编辑哦,我明白了 - 你在倒退!杜尔。如果您继续浏览节点列表,它应该可以工作。

Your code sets the containing block to "display: none". After that, it doesn't matter that the inner <div> is "display: block".

Your diagnostic technique of dumping out the element is flawed. If you use something like the Chrome debugger or Firebug, you'll see that your "ShowThis" element does indeed have "display: block" in its "style" attribute. However, it doesn't show up because all its parent elements (including the <body> tag) are still "display: none".

edit I think the problem is probably something that stems from the order in which the page elements appear in the "getElementsByTagName()" result. If you reach the parent elements after the child elements, then they'll be set to "display: none" after they've been set to "display: block".

edit again — confirmed. The elements are returned from "getElementsByTagName()" appear in reverse order that they appear in the HTML. Thus, the last element your code sees in the outer loop is the container <div> for the "ShowThis" <div>.

edit yet again oh dang I see - you're going backwards!! Durr. If you go forward through the node list, it should work.

烏雲後面有陽光 2024-12-10 04:28:00

您的问题是,隐藏所有内容的外循环将在您设置为 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();

You issue is that your outer loop that hides everything will hide the 'showthis' node's parents after you set then to display='block'. If you split the hiding and showing into two steps, it works fine.

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;
    }
}

Also, just for the record, this type of thing is where jQuery is awesome.

jQuery('*').hide();
jQuery('.ShowThis').show().parents().show();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文