我想要:

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

有好的替代品吗?


当前回答

这几乎适用于任何浏览器。(这里没有元素和节点的区别)

function dom_element_check(element){
    if (typeof element.nodeType !== 'undefined'){
        return true;
    }
    return false;
}

其他回答

我认为你要做的是彻底检查一些属性,它们总是在一个dom元素中,但它们的组合不太可能在另一个对象中,像这样:

var isDom = function (inp) {
    return inp && inp.tagName && inp.nodeName && inp.ownerDocument && inp.removeAttribute;
};

使用这里发现的根检测,我们可以确定例如alert是否是对象根的成员,那么它很可能是一个窗口:

function isInAnyDOM(o) { 
  return (o !== null) && !!(o.ownerDocument && (o.ownerDocument.defaultView || o.ownerDocument.parentWindow).alert); // true|false
}

要确定对象是否是当前窗口甚至更简单:

function isInCurrentDOM(o) { 
  return (o !== null) && !!o.ownerDocument && (window === (o.ownerDocument.defaultView || o.ownerDocument.parentWindow)); // true|false
}

这似乎比开头线程中的try/catch解决方案更便宜。

没有P

不是为了强调这一点,而是为了兼容es5的浏览器,为什么不直接:

function isDOM(e) {
  return (/HTML(?:.*)Element/).test(Object.prototype.toString.call(e).slice(8, -1));
}

不会工作在文本节点和不确定的影子DOM或DocumentFragments等,但将工作在几乎所有的HTML标签元素。

Lo-Dash的_.isElement怎么样?

$ npm install lodash.iselement

在代码中:

var isElement = require("lodash.iselement");
isElement(document.body);

您可以查看所讨论的对象或节点是否返回字符串类型。

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