如何在不使用getElementById方法的情况下测试元素的存在性?

我已经设置了一个现场演示供参考。我也将在这里打印代码:

<!DOCTYPE html>
<html>
<head>
    <script>
    var getRandomID = function (size) {
            var str = "",
                i = 0,
                chars = "0123456789abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ";
            while (i < size) {
                str += chars.substr(Math.floor(Math.random() * 62), 1);
                i++;
            }
            return str;
        },
        isNull = function (element) {
            var randomID = getRandomID(12),
                savedID = (element.id)? element.id : null;
            element.id = randomID;
            var foundElm = document.getElementById(randomID);
            element.removeAttribute('id');
            if (savedID !== null) {
                element.id = savedID;
            }
            return (foundElm) ? false : true;
        };
    window.onload = function () {
        var image = document.getElementById("demo");
        console.log('undefined', (typeof image === 'undefined') ? true : false); // false
        console.log('null', (image === null) ? true : false); // false
        console.log('find-by-id', isNull(image)); // false
        image.parentNode.removeChild(image);
        console.log('undefined', (typeof image === 'undefined') ? true : false); // false ~ should be true?
        console.log('null', (image === null) ? true : false); // false ~ should be true?
        console.log('find-by-id', isNull(image)); // true ~ correct but there must be a better way than this?
    };
    </script>
</head>
<body>
    <div id="demo"></div>
</body>
</html>

基本上,上面的代码演示了一个元素被存储到一个变量中,然后从DOM中删除。即使元素已经从DOM中删除,变量仍然保留第一次声明时的元素。换句话说,它不是对元素本身的动态引用,而是一个副本。因此,检查变量的值(元素)是否存在将会得到一个意想不到的结果。

isNull函数是我试图从变量中检查元素的存在,它可以工作,但我想知道是否有更简单的方法来实现相同的结果。

PS:如果有人知道一些与这个主题相关的好文章,我还对JavaScript变量为什么会这样表现感兴趣。


当前回答

似乎有些人登陆这里,只是想知道一个元素是否存在(与最初的问题略有不同)。

这就像使用浏览器的任何选择方法一样简单,并检查它的真值(通常)。

例如,如果我的元素有一个id为“find-me”,我可以简单地使用…

var elementExists = document.getElementById("find-me");

指定此参数以返回对元素的引用或null。如果必须使用布尔值,只需抛出一个!!在方法调用之前。

此外,你还可以使用其他一些方法来查找元素,比如(all living off document):

querySelector () / querySelectorAll () getElementsByClassName () getElementsByName ()

其中一些方法返回一个NodeList,因此一定要检查它的length属性,因为NodeList是一个对象,因此是真值。


对于实际确定一个元素是否作为可见DOM的一部分存在(就像最初提出的问题一样),Csuwldcat提供了比滚动自己的解决方案更好的解决方案(就像这个答案曾经包含的那样)。也就是说,在DOM元素上使用contains()方法。

你可以这样使用它……

document.body.contains(someReferenceToADomElement);

其他回答

最简单的解决方案是检查baseURI属性,该属性仅在元素插入DOM时设置,并且在删除它时恢复为空字符串。

var div = document.querySelector('div'); // "div"在DOM中,所以应该打印一个字符串 console.log (div.baseURI); //从DOM中删除"div document.body.removeChild (div); //输出一个空字符串 console.log (div.baseURI); < div > < / div >

您可以检查parentNode属性是否为空。

也就是说,

if(!myElement.parentNode)
{
    // The node is NOT in the DOM
}
else
{
    // The element is in the DOM
}

而不是迭代父元素,当元素从DOM中分离出来时,你可以得到一个全为0的边界矩形:

function isInDOM(element) {
    if (!element)
        return false;
    var rect = element.getBoundingClientRect();
    return (rect.top || rect.left || rect.height || rect.width)?true:false;
}

如果你想处理宽度和高度都为零的元素的边缘情况,你可以通过迭代父元素直到document.body:

function isInDOM(element) {
    if (!element)
        return false;
    var rect = element.getBoundingClientRect();
    if (element.top || element.left || element.height || element.width)
        return true;
    while(element) {
        if (element == document.body)
            return true;
        element = element.parentNode;
    }
    return false;
}

如果getElementById()可用,请使用它。

另外,这里有一个简单的方法来用jQuery:

if ($('#elementId').length > 0) {
  // Exists.
}

如果你不能使用第三方库,那就坚持使用基本的JavaScript:

var element =  document.getElementById('elementId');
if (typeof(element) != 'undefined' && element != null)
{
  // Exists.
}

如果一个元素在DOM中,它的父元素也应该在DOM中 最后一个祖父结点应该是文档

为了检查,我们循环到元素的parentNode树,直到我们到达最后一个祖父结点

用这个:

/**
 * @param {HTMLElement} element - The element to check
 * @param {boolean}     inBody  - Checks if the element is in the body
 * @return {boolean}
 */
var isInDOM = function(element, inBody) {
    var _ = element, last;

    while (_) {
        last = _;
        if (inBody && last === document.body) { break;}
        _ = _.parentNode;
    }

    return inBody ? last === document.body : last === document;
};