我想要:

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

在我自己的脚本中,我曾经只使用这个,因为我从来不需要tagName作为属性:

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

所以对于第二个目标,我想出了下面的快速解决方案——这基本上是有效的。;)

问题是,它依赖于浏览器强制执行只读属性,而并非所有浏览器都这样做。

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

有好的替代品吗?


当前回答

也许这是另一种选择?在Opera 11, FireFox 6, Internet Explorer 8, Safari 5和谷歌Chrome 16中测试。

function isDOMNode(v) {
  if ( v===null ) return false;
  if ( typeof v!=='object' ) return false;
  if ( !('nodeName' in v) ) return false; 

  var nn = v.nodeName;
  try {
    // DOM node property nodeName is readonly.
    // Most browsers throws an error...
    v.nodeName = 'is readonly?';
  } catch (e) {
    // ... indicating v is a DOM node ...
    return true;
  }
  // ...but others silently ignore the attempt to set the nodeName.
  if ( v.nodeName===nn ) return true;
  // Property nodeName set (and reset) - v is not a DOM node.
  v.nodeName = nn;

  return false;
}

函数不会被例如这个所欺骗

isDOMNode( {'nodeName':'fake'} ); // returns false

其他回答

如果你正在使用jQuery,试试这个

$('<div>').is('*') // true
$({tagName: 'a'}).is('*') // false
$({}).is('*') // false
$([]).is('*') // false
$(0).is('*') // false
$(NaN).is('*') // false

我使用这个函数:

函数isHTMLDOMElement(obj) { if (Object.prototype.toString.call(obj).slice(-8) === 'Element]') { 如果(Object.prototype.toString.call (obj)。slice(0,12) === '[object HTML') { 返回true; } 返回错误; } 返回错误; }

https://jsfiddle.net/1qazxsw2/wz7e0fvj/9/

在Firefox中,您可以使用Node实例。该节点在DOM1中定义。

但在IE中就没那么容易了。

"instanceof ActiveXObject"只能说明它是一个本机对象。 “typeof document.body。appendChild=='object'"说明它可以是DOM对象,也可以是其他具有相同功能的对象。

如果有任何异常,只能使用DOM函数和catch来确保它是DOM元素。然而,它可能有副作用(例如改变对象内部状态/性能/内存泄漏)

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.

这是来自可爱的JavaScript库MooTools:

if (obj.nodeName){
    switch (obj.nodeType){
    case 1: return 'element';
    case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
    }
}