How do you check if a JavaScript Object is a DOM Object?

后端 未结 30 2518
-上瘾入骨i
-上瘾入骨i 2020-11-22 16:06

I\'m trying to get:

document.createElement(\'div\')  //=> true
{tagName: \'foobar something\'}  //=> false

In my own scripts, I used

相关标签:
30条回答
  • 2020-11-22 16:38

    All solutions above and below (my solution including) suffer from possibility of being incorrect, especially on IE — it is quite possible to (re)define some objects/methods/properties to mimic a DOM node rendering the test invalid.

    So usually I use the duck-typing-style testing: I test specifically for things I use. For example, if I want to clone a node I test it like this:

    if(typeof node == "object" && "nodeType" in node &&
       node.nodeType === 1 && node.cloneNode){
      // most probably this is a DOM node, we can clone it safely
      clonedNode = node.cloneNode(false);
    }
    

    Basically it is a little sanity check + the direct test for a method (or a property) I am planning to use.

    Incidentally the test above is a good test for DOM nodes on all browsers. But if you want to be on the safe side always check the presence of methods and properties and verify their types.

    EDIT: IE uses ActiveX objects to represent nodes, so their properties do not behave as true JavaScript object, for example:

    console.log(typeof node.cloneNode);              // object
    console.log(node.cloneNode instanceof Function); // false
    

    while it should return "function" and true respectively. The only way to test methods is to see if the are defined.

    0 讨论(0)
  • 2020-11-22 16:39

    This is from the lovely JavaScript library MooTools:

    if (obj.nodeName){
        switch (obj.nodeType){
        case 1: return 'element';
        case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
        }
    }
    
    0 讨论(0)
  • 2020-11-22 16:41

    I think prototyping is not a very good solution but maybe this is the fastest one: Define this code block;

    Element.prototype.isDomElement = true;
    HTMLElement.prototype.isDomElement = true;
    

    than check your objects isDomElement property:

    if(a.isDomElement){}
    

    I hope this helps.

    0 讨论(0)
  • 2020-11-22 16:41

    This will work for almost any browser. (No distinction between elements and nodes here)

    function dom_element_check(element){
        if (typeof element.nodeType !== 'undefined'){
            return true;
        }
        return false;
    }
    
    0 讨论(0)
  • 2020-11-22 16:42

    How about Lo-Dash's _.isElement?

    $ npm install lodash.iselement
    

    And in the code:

    var isElement = require("lodash.iselement");
    isElement(document.body);
    
    0 讨论(0)
  • 2020-11-22 16:42

    This is what I figured out:

    var isHTMLElement = (function () {
        if ("HTMLElement" in window) {
            // Voilà. Quick and easy. And reliable.
            return function (el) {return el instanceof HTMLElement;};
        } else if ((document.createElement("a")).constructor) {
            // We can access an element's constructor. So, this is not IE7
            var ElementConstructors = {}, nodeName;
            return function (el) {
                return el && typeof el.nodeName === "string" &&
                     (el instanceof ((nodeName = el.nodeName.toLowerCase()) in ElementConstructors 
                        ? ElementConstructors[nodeName] 
                        : (ElementConstructors[nodeName] = (document.createElement(nodeName)).constructor)))
            }
        } else {
            // Not that reliable, but we don't seem to have another choice. Probably IE7
            return function (el) {
                return typeof el === "object" && el.nodeType === 1 && typeof el.nodeName === "string";
            }
        }
    })();
    

    To improve performance I created a self-invoking function that tests the browser's capabilities only once and assigns the appropriate function accordingly.

    The first test should work in most modern browsers and was already discussed here. It just tests if the element is an instance of HTMLElement. Very straightforward.

    The second one is the most interesting one. This is its core-functionality:

    return el instanceof (document.createElement(el.nodeName)).constructor
    

    It tests whether el is an instance of the construcor it pretends to be. To do that, we need access to an element's contructor. That's why we're testing this in the if-Statement. IE7 for example fails this, because (document.createElement("a")).constructor is undefined in IE7.

    The problem with this approach is that document.createElement is really not the fastest function and could easily slow down your application if you're testing a lot of elements with it. To solve this, I decided to cache the constructors. The object ElementConstructors has nodeNames as keys with its corresponding constructors as values. If a constructor is already cached, it uses it from the cache, otherwise it creates the Element, caches its constructor for future access and then tests against it.

    The third test is the unpleasant fallback. It tests whether el is an object, has a nodeType property set to 1 and a string as nodeName. This is not very reliable of course, yet the vast majority of users shouldn't even fall back so far.

    This is the most reliable approach I came up with while still keeping performance as high as possible.

    0 讨论(0)
提交回复
热议问题