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 ]

2 голосов
/ 28 ноября 2016

Нет необходимости во взломах, вы можете просто спросить, является ли элемент экземпляром Элемента :

const isElement = el => el instanceof Element
2 голосов
/ 15 июня 2017

Я предлагаю простой способ проверки, является ли переменная элементом DOM

    function isDomEntity(entity) {

        if( typeof entity   === 'object' && entity.nodeType != undefined){
            return true;
        }
        else{
            return false;
        }
    }
2 голосов
/ 30 декабря 2014

Для тех, кто использует Angular:

angular.isElement

https://docs.angularjs.org/api/ng/function/angular.isElement

2 голосов
/ 23 августа 2012

Вы можете увидеть, возвращает ли рассматриваемый объект или узел строковый тип.

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
1 голос
/ 21 декабря 2008

В Firefox вы можете использовать instanceof Node. Node определено в DOM1 .

Но в IE это не так просто.

  1. «instanceof ActiveXObject» может только сказать, что это собственный объект.
  2. "typeof document.body.appendChild == 'object'" говорит о том, что это может быть объект DOM, но также может быть что-то еще с такой же функцией

Вы можете только убедиться, что это элемент DOM, используя функцию DOM, и перехватывать, если есть какие-либо исключения. Однако он может иметь побочный эффект (например, изменить внутреннее состояние объекта / производительность / утечку памяти)

1 голос
/ 07 февраля 2013

Вот что я понял:

var isHTMLElement = (function () {
    if ("HTMLElement" in window) {
        // Voilà. Quick and easy. And reliable.
        return function (el) {return el instanceof HTMLElement;};
    } else if ((document.createElement("a")).constructor) {
        // We can access an element's constructor. So, this is not IE7
        var ElementConstructors = {}, nodeName;
        return function (el) {
            return el && typeof el.nodeName === "string" &&
                 (el instanceof ((nodeName = el.nodeName.toLowerCase()) in ElementConstructors 
                    ? ElementConstructors[nodeName] 
                    : (ElementConstructors[nodeName] = (document.createElement(nodeName)).constructor)))
        }
    } else {
        // Not that reliable, but we don't seem to have another choice. Probably IE7
        return function (el) {
            return typeof el === "object" && el.nodeType === 1 && typeof el.nodeName === "string";
        }
    }
})();

Чтобы повысить производительность, я создал функцию самовывоза, которая проверяет возможности браузера только один раз и назначает соответствующую функцию соответствующим образом.

Первый тест должен работать в большинстве современных браузеров и уже обсуждался здесь. Он просто проверяет, является ли элемент экземпляром HTMLElement. Очень просто.

Второй - самый интересный. Это его основная функциональность:

return el instanceof (document.createElement(el.nodeName)).constructor

Он проверяет, является ли el экземпляром конструкции, которой он притворяется. Для этого нам нужен доступ к конструктору элемента. Вот почему мы проверяем это в if-Statement. Например, IE7 терпит неудачу, потому что (document.createElement("a")).constructor - это undefined в IE7.

Проблема с этим подходом заключается в том, что document.createElement на самом деле не самая быстрая функция, и она может легко замедлить работу вашего приложения, если вы тестируете с ним много элементов. Чтобы решить эту проблему, я решил кешировать конструкторы. Объект ElementConstructors имеет nodeNames в качестве ключей и соответствующие конструкторы в качестве значений. Если конструктор уже кэширован, он использует его из кэша, в противном случае он создает элемент, кэширует его конструктор для последующего доступа и затем проверяет его.

Третий тест - неприятный запасной вариант. Он проверяет, является ли el object, имеет ли свойство nodeType, установленное на 1, и строку как nodeName. Конечно, это не очень надежно, но подавляющему большинству пользователей пока не стоит отступать.

Это самый надежный подход, который я придумал, сохраняя при этом максимально возможную производительность.

1 голос
/ 05 января 2012

Возможно, это альтернатива? Протестировано в Opera 11, FireFox 6, Internet Explorer 8, Safari 5 и Google 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
1 голос
/ 28 апреля 2014

Проверьте, наследуется ли obj от Узел .

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

Узел - это базовый интерфейс , от которого наследуются HTMLElement и Text.

1 голос
/ 28 декабря 2015

отличает необработанный объект js от элемента HTMLE

function isDOM (x){
     return /HTML/.test( {}.toString.call(x) );
 }

использование:

isDOM( {a:1} ) // false
isDOM( document.body ) // true

// ИЛИ

Object.defineProperty(Object.prototype, "is",
    {
        value: function (x) {
            return {}.toString.call(this).indexOf(x) >= 0;
        }
    });

использование:

o={}; o.is("HTML") // false o=document.body; o.is("HTML") // true

1 голос
/ 04 ноября 2015

Я думаю, что прототипирование не очень хорошее решение, но, возможно, это самое быстрое: Определите этот блок кода;

Element.prototype.isDomElement = true;
HTMLElement.prototype.isDomElement = true;

чем проверить ваши объекты isDomElement свойство:

if(a.isDomElement){}

Надеюсь, это поможет.

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