JavaScript isDOM — How do you check if a JavaScrip

2018-12-31 20:11发布

I'm trying to get:

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

In my own scripts, I used to just use this since I never needed tagName as a property:

if (!object.tagName) throw ...;

So for the second object, I came up with the following as a quick solution -- which mostly works. ;)

The problem is, it depends on browsers enforcing read-only properties, which not all do.

function isDOM(obj) {
  var tag = obj.tagName;
  try {
    obj.tagName = '';  // Read-only for DOM, should throw exception
    obj.tagName = tag; // Restore for normal objects
    return false;
  } catch (e) {
    return true;
  }
}

Is there a good substitute?

30条回答
有味是清欢
2楼-- · 2018-12-31 20:37

I suggest a simple way to testing if a variable is an DOM element

    function isDomEntity(entity) {

        if( typeof entity   === 'object' && entity.nodeType != undefined){
            return true;
        }
        else{
            return false;
        }
    }
查看更多
大哥的爱人
3楼-- · 2018-12-31 20:38

How about Lo-Dash's _.isElement?

$ npm install lodash.iselement

And in the code:

var isElement = require("lodash.iselement");
isElement(document.body);
查看更多
像晚风撩人
4楼-- · 2018-12-31 20:38

You can see if the object or node in question returns a string type.

typeof (array).innerHTML === "string" => false
typeof (object).innerHTML === "string" => false
typeof (number).innerHTML === "string" => false
typeof (text).innerHTML === "string" => false

//any DOM element will test as true
typeof (HTML object).innerHTML === "string" => true
typeof (document.createElement('anything')).innerHTML === "string" => true
查看更多
零度萤火
5楼-- · 2018-12-31 20:38
var isElement = function(e){
    try{
        // if e is an element attached to the DOM, we trace its lineage and use native functions to confirm its pedigree
        var a = [e], t, s, l = 0, h = document.getElementsByTagName('HEAD')[0], ht = document.getElementsByTagName('HTML')[0];
        while(l!=document.body&&l!=h&&l.parentNode) l = a[a.push(l.parentNode)-1];
        t = a[a.length-1];
        s = document.createElement('SCRIPT');   // safe to place anywhere and it won't show up
        while(a.length>1){  // assume the top node is an element for now...
            var p = a.pop(),n = a[a.length-1];
            p.insertBefore(s,n);
        }
        if(s.parentNode)s.parentNode.removeChild(s);
        if(t!=document.body&&t!=h&&t!=ht)
            // the top node is not attached to the document, so we don't have to worry about it resetting any dynamic media
            // test the top node
            document.createElement('DIV').appendChild(t).parentNode.removeChild(t);
        return e;
    }
    catch(e){}
    return null;
}

I tested this on Firefox, Safari, Chrome, Opera and IE9. I couldn't find a way to hack it.
In theory, it tests every ancestor of the proposed element, as well as the element itself, by inserting a script tag before it.
If its first ancestor traces back to a known element, such as <html>, <head> or <body>, and it hasn't thrown an error along the way, we have an element.
If the first ancestor is not attached to the document, we create an element and attempt to place the proposed element inside of it, (and then remove it from the new element).
So it either traces back to a known element, successfully attaches to a known element or fails.
It returns the element or null if it is not an element.

查看更多
泪湿衣
6楼-- · 2018-12-31 20:39
var IsPlainObject = function ( obj ) { return obj instanceof Object && ! ( obj instanceof Function || obj.toString( ) !== '[object Object]' || obj.constructor.name !== 'Object' ); },
    IsDOMObject = function ( obj ) { return obj instanceof EventTarget; },
    IsDOMElement = function ( obj ) { return obj instanceof Node; },
    IsListObject = function ( obj ) { return obj instanceof Array || obj instanceof NodeList; },

// In fact I am more likely t use these inline, but sometimes it is good to have these shortcuts for setup code

查看更多
君临天下
7楼-- · 2018-12-31 20:39

I have a special way to do this that has not yet been mentioned in the answers.

My solution is based on four tests. If the object passes all four, then it is an element:

  1. The object is not null.

  2. The object has a method called "appendChild".

  3. The method "appendChild" was inherited from the Node class, and isn't just an imposter method (a user-created property with an identical name).

  4. The object is of Node Type 1 (Element). Objects that inherit methods from the Node class are always Nodes, but not necessarily Elements.

Q: How do I check if a given property is inherited and isn't just an imposter?

A: A simple test to see if a method was truly inherited from Node is to first verify that the property has a type of "object" or "function". Next, convert the property to a string and check if the result contains the text "[Native Code]". If the result looks something like this:

function appendChild(){
[Native Code]
}

Then the method has been inherited from the Node object. See https://davidwalsh.name/detect-native-function

And finally, bringing all the tests together, the solution is:

function ObjectIsElement(obj) {
    var IsElem = true;
    if (obj == null) {
        IsElem = false;
    } else if (typeof(obj.appendChild) != "object" && typeof(obj.appendChild) != "function") {
        //IE8 and below returns "object" when getting the type of a function, IE9+ returns "function"
        IsElem = false;
    } else if ((obj.appendChild + '').replace(/[\r\n\t\b\f\v\xC2\xA0\x00-\x1F\x7F-\x9F ]/ig, '').search(/\{\[NativeCode]}$/i) == -1) {
        IsElem = false;
    } else if (obj.nodeType != 1) {
        IsElem = false;
    }
    return IsElem;
}
查看更多
登录 后发表回答