我想要:

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

有好的替代品吗?


当前回答

上面和下面的所有解决方案(包括我的解决方案)都有可能是不正确的,特别是在IE上——(重新)定义一些对象/方法/属性来模拟DOM节点,使测试无效是很可能的。

所以我通常使用duck-typing风格的测试:我专门测试我使用的东西。例如,如果我想克隆一个节点,我这样测试它:

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

基本上,它是一个小的完整性检查+对我计划使用的方法(或属性)的直接测试。

顺便说一句,上面的测试对于所有浏览器上的DOM节点来说都是一个很好的测试。但是如果您想要安全起见,请始终检查方法和属性的存在并验证它们的类型。

编辑:IE使用ActiveX对象来表示节点,因此它们的属性行为不像真正的JavaScript对象,例如:

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

而它应该分别返回“function”和true。测试方法的唯一方法是查看是否定义了方法。

其他回答

根据mdn

Element是Document中所有对象都继承的最通用基类。它只有对所有类型的元素通用的方法和属性。

我们可以通过原型实现isElement。以下是我的建议:

/** * @description detect if obj is an element * @param {*} obj * @returns {Boolean} * @example * see below */ function isElement(obj) { if (typeof obj !== 'object') { return false } let prototypeStr, prototype do { prototype = Object.getPrototypeOf(obj) // to work in iframe prototypeStr = Object.prototype.toString.call(prototype) // '[object Document]' is used to detect document if ( prototypeStr === '[object Element]' || prototypeStr === '[object Document]' ) { return true } obj = prototype // null is the terminal of object } while (prototype !== null) return false } console.log(isElement(document)) // true console.log(isElement(document.documentElement)) // true console.log(isElement(document.body)) // true console.log(isElement(document.getElementsByTagName('svg')[0])) // true or false, decided by whether there is svg element console.log(isElement(document.getElementsByTagName('svg'))) // false console.log(isElement(document.createDocumentFragment())) // false

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

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

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

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

这是来自可爱的JavaScript库MooTools:

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

上面和下面的所有解决方案(包括我的解决方案)都有可能是不正确的,特别是在IE上——(重新)定义一些对象/方法/属性来模拟DOM节点,使测试无效是很可能的。

所以我通常使用duck-typing风格的测试:我专门测试我使用的东西。例如,如果我想克隆一个节点,我这样测试它:

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

基本上,它是一个小的完整性检查+对我计划使用的方法(或属性)的直接测试。

顺便说一句,上面的测试对于所有浏览器上的DOM节点来说都是一个很好的测试。但是如果您想要安全起见,请始终检查方法和属性的存在并验证它们的类型。

编辑:IE使用ActiveX对象来表示节点,因此它们的属性行为不像真正的JavaScript对象,例如:

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

而它应该分别返回“function”和true。测试方法的唯一方法是查看是否定义了方法。

接受的答案有点复杂,并且没有检测到所有类型的HTML元素。例如,不支持SVG元素。相反,这个答案适用于HTML和SVG等。

在这里查看它的实际操作:https://jsfiddle.net/eLuhbu6r/

function isElement(element) {
    return element instanceof Element || element instanceof HTMLDocument;  
}

锦上添花:上面的代码与IE8兼容。