我想要:

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

有好的替代品吗?


当前回答

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

//事实上我更倾向于内联使用这些快捷方式,但有时为设置代码提供这些快捷方式是很好的

其他回答

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

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

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

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

你可能会感兴趣:

function isElement(obj) {
  try {
    //Using W3 DOM2 (works for FF, Opera and Chrome)
    return obj instanceof HTMLElement;
  }
  catch(e){
    //Browsers not supporting W3 DOM2 don't have HTMLElement and
    //an exception is thrown and we end up here. Testing some
    //properties that all elements have (works on IE7)
    return (typeof obj==="object") &&
      (obj.nodeType===1) && (typeof obj.style === "object") &&
      (typeof obj.ownerDocument ==="object");
  }
}

它是DOM的一部分,第2层。

更新2:这是我如何在我自己的库中实现它: (之前的代码在Chrome中不起作用,因为Node和HTMLElement是函数而不是预期的对象。这段代码在FF3, IE7, Chrome 1和Opera 9中进行了测试。

//Returns true if it is a DOM node
function isNode(o){
  return (
    typeof Node === "object" ? o instanceof Node : 
    o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName==="string"
  );
}

//Returns true if it is a DOM element    
function isElement(o){
  return (
    typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2
    o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName==="string"
);
}

测试变量是否是DOM元素的简单方法(冗长,但更传统的语法:-)

function isDomEntity(entity) {
  if(typeof entity  === 'object' && entity.nodeType !== undefined){
     return true;
  }
  else{
     return false;
  }
}

或者像HTMLGuy建议的那样(简洁的语法):

const isDomEntity = entity =>
  typeof entity === 'object' && entity.nodeType !== undefined

测试obj是否继承自Node。

if (obj instanceof Node){
    // obj is a DOM Object
}

Node是HTMLElement和Text继承的一个基本接口。

大多数答案使用某种鸭子类型,例如检查对象是否具有nodeType属性。但这还不够,因为非节点也可以具有类节点属性。

另一种常见的方法是instanceof,它会产生误报,例如Object.create(Node),尽管继承了节点属性,但它不是节点。

此外,上述两种方法都调用内部基本方法,这可能会有问题,例如,如果测试的值是一个代理。

相反,我建议借用一个节点方法并在我们的对象上调用它。浏览器可能会通过查看代理中不可自定义的内部槽来检查该值是否是一个节点,因此即使它们也无法干扰我们的检查。

function isNode(value) {
  try {
    Node.prototype.cloneNode.call(value, false);
    return true;
  } catch(err) {
    return false;
  }
}

如果您愿意,还可以使用属性getter。

函数isNode(value) { 尝试{ Object.getOwnPropertyDescriptor (Node.prototype nodeType) .get.call(价值); 返回true; } catch(err) { 返回错误; } }

类似地,如果您想测试一个值是否是一个元素,您可以使用

function isElement(value) {
  try {
    Element.prototype.getAttribute.call(value, '');
    return true;
  } catch(err) {
    return false;
  }
}
function isHTMLElement(value) {
  try {
    HTMLElement.prototype.click.call(value);
    return true;
  } catch(err) {
    return false;
  }
}