Search code examples
javascriptdomselectors-api

Is it reliable to only check if an argument is a node before using querySelectorAll on it?


Currently, I see that the method querySelectorAll is found on the document which is a node and not an element, and found on HTML elements.

I am working with a function that accepts as the first parameter, either a node, element, or a selector that then finds an element. I need to check type of node, because the function should work is document is passed in.

function queryElement(elementOrSelector) {
    if (!isNode(elementOrSelector)) {
        elementOrSelector = document.querySelector(elementOrSelector);
    }
    // This next line is the line I worry about
    var possibleElements = elementOrSelector.querySelector('[test]');
    ...
}

function isNode(o) {
    return (
        typeof Node === "object" ? o instanceof Node :
        o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName === "string"
    );
}

This allows me to pass in the following:

queryElement(document);
// or
queryElement(document.querySelector('select'));

and they will all work. But right now, I am only checking to see if they are of type node when technically, the querySelectorAll method only exists on the document, and the HTML Element prototype. I believe that Element inherits from Node so that is why most of it is working. But if I only ever check type of node, will I run into problems? Is there a particular node that is also not an Element that will not have querySelectorAll available to it?


Solution

  • Is there a particular node that is also not an Element that will not have querySelectorAll available to it?

    Yes. For example:

    • Attribute nodes (removed in DOM4)
    • Doctypes
    • Text nodes
    • Comment nodes

    I think the only reliable way to check if something is a node is attempting to use it as a node, and see if it throws an error.

    However, checking if the object has a querySelector property (and maybe that its value is a function) is probably enough.