JavaScript isDOM - Как проверить, является ли объект JavaScript объектом DOM? - PullRequest
213 голосов
/ 21 декабря 2008

Я пытаюсь получить:

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

Есть хороший заменитель?

Ответы [ 32 ]

267 голосов
/ 21 декабря 2008

Это может представлять интерес:

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, Level2 .

Обновление 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"
);
}
36 голосов
/ 27 апреля 2016

Следующий супер-простой код, совместимый с IE8, прекрасно работает.

Принятый ответ не обнаруживает все типы элементов HTML. Например, элементы SVG не поддерживаются. В отличие от этого, этот ответ работает для HTML хорошо, как SVG.

Смотрите это в действии здесь: https://jsfiddle.net/eLuhbu6r/

function isElement(element) {
    return element instanceof Element || element instanceof HTMLDocument;  
}
11 голосов
/ 22 декабря 2008

Все решения выше и ниже (включая мое решение) подвержены ошибкам, особенно в IE & mdash; вполне возможно (пере) определить некоторые объекты / методы / свойства для имитации узла DOM, делающего тест недействительным.

Поэтому обычно я использую тестирование в стиле утиной типографии: я тестирую специально для того, что использую. Например, если я хочу клонировать узел, я проверяю его следующим образом:

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

в то время как он должен возвращать «функцию» и true соответственно. Единственный способ проверить методы - это определить, определены ли они.

7 голосов
/ 21 декабря 2008

Вы можете попробовать добавить его к реальному DOM-узлу ...

function isDom(obj)
{
    var elm = document.createElement('div');
    try
    {
        elm.appendChild(obj);
    }
    catch (e)
    {
        return false;
    }

    return true;
}
7 голосов
/ 24 ноября 2014

Как насчет Ло-Даша _.isElement?

$ npm install lodash.iselement

И в коде:

var isElement = require("lodash.iselement");
isElement(document.body);
5 голосов
/ 21 декабря 2008

Это из прекрасной библиотеки JavaScript MooTools :

if (obj.nodeName){
    switch (obj.nodeType){
    case 1: return 'element';
    case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
    }
}
4 голосов
/ 09 декабря 2013

Используя обнаружение корня, найденное здесь , мы можем определить, например, 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 в начальном потоке.

Дон П

4 голосов
/ 02 марта 2011

старая тема, но вот обновленная возможность для ie8 и ff3.5 пользователей:

function isHTMLElement(o) {
    return (o.constructor.toString().search(/\object HTML.+Element/) > -1);
}
3 голосов
/ 22 декабря 2013
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; },

// На самом деле я, скорее всего, использую эти строки, но иногда полезно иметь эти ярлыки для кода установки

3 голосов
/ 22 октября 2014

Это может быть полезно: isDOM

//-----------------------------------
// Determines if the @obj parameter is a DOM element
function isDOM (obj) {
    // DOM, Level2
    if ("HTMLElement" in window) {
        return (obj && obj instanceof HTMLElement);
    }
    // Older browsers
    return !!(obj && typeof obj === "object" && obj.nodeType === 1 && obj.nodeName);
}

В приведенном выше коде мы используем оператор с двойным отрицанием *1009*, чтобы получить логическое значение объекта, переданного в качестве аргумента. Таким образом, мы гарантируем, что каждое выражение, вычисленное в условном выражении, будет логическим, используя преимущество Оценка короткого замыкания , таким образом, функция возвращает true или false

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...