Как проверить, является ли объект JavaScript объектом DOM?

248

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

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

Есть хорошая замена?

Джонатан Лоновски
источник
3
Неужели я не понимаю, должен ли «объект DOM» охватывать не только элементы, но и все узлы (текстовые узлы, атрибуты и т. Д.)? Все ответы и то, как вы задали вопрос, как правило, наводят на мысль, что этот вопрос конкретно об элементах ...
Майк Грызун

Ответы:

300

Это может быть интересно:

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"
);
}
некоторые
источник
11
Стоит отметить, что это не будет работать с элементами, которые принадлежат другим окнам / фреймам. Рекомендовано использование утки
Энди Э
2
Вы можете обмануть его:function Fake() {}; Fake.prototype=document.createElement("div"); alert(new Fake() instanceof HTMLElement);
Ядро Джеймс
11
WTF факт: Firefox 5 и более ранние версии возвращения trueк [] instanceof HTMLElement.
Роб Вт
6
Кстати, HTMLElementвсегда a function, поэтому typeofвыкинет вас из колеи и выполнит вторую часть оператора. Вы могли бы попробовать , если вы хотите instanceof Object, потому что функция будет экземпляром Objectили просто явно проверить typeof === "function", потому что Nodeи HTMLElementоба являются носителями функции объекта.
Роланд
2
Когда вы звоните isElement(0), он возвращает 0, а не ложь ... Почему это так, и как я могу предотвратить это?
Джессика
68

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

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

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

function isElement(element) {
    return element instanceof Element || element instanceof HTMLDocument;  
}
Монарх Вадия
источник
3
«Элемент» не определен в IE7
Дан
49
Я придерживаюсь мнения, что любой, кто все еще использует IE7, должен потратить пять секунд, чтобы загрузить лучший браузер, вместо того, чтобы позволить нам потратить несколько дней или недель на то, чтобы отказаться от времени.
Мопсид
1
Я согласен с @mopsyd, но автор ответа заявляет, что он работает в IE7, который может потребоваться обновить для корректности.
Лайош Месарос
1
Обновлено, чтобы сказать IE9. Я не уверен, что IE8 поддерживает это.
Монарх Вадия
1
@MonarchWadia да, это поддерживается в IE8. Но обратите внимание, что это не возвращает true для documentэлемента (во всех браузерах). если вам это нужно, вы должны попробовать:x instanceof Element || x instanceof HTMLDocument
S.Serpooshan
11

Все решения выше и ниже (включая мое решение) страдают от возможности быть некорректными, особенно в IE - вполне возможно (пере) определить некоторые объекты / методы / свойства для имитации узла 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соответственно. Единственный способ проверить методы - это определить, определены ли они.

Евгений Лазуткин
источник
"typeof document.body.cloneNode" действительно возвращает "объект" в моем IE
Деннис C
Это выглядит как достойный ответ. См. Мой ответ ниже, хотя, stackoverflow.com/a/36894871/1204556
Монарх Вадия
8

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

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

    return true;
}
Greg
источник
11
Это работает? Это все еще решение. Творческий в этом.
Джастин Мейер
3
+1 за креативность и уверенность в этом. Однако, если узел уже является частью DOM, вы просто удалили его! Итак ... этот ответ неполон, если не выполнить работу по повторному добавлению элемента в DOM, если это необходимо.
svidgen
4
Я читаю это спустя почти 5 лет, и я думаю, что это один из самых крутых. Это просто нужно доработать. Например, вы можете попытаться добавить клон узла в отдельный элемент. Если это не объект DOM. что-то обязательно пойдет не так. Тем не менее, это довольно дорогое решение.
MaxArt
Или вместо того , чтобы пытаться присоединить клон элемента, просто пытается клонировать его должно быть достаточно: obj.cloneNode(false). И не имеет побочных эффектов.
mauroc8
1
Это действительно дорого и излишне сложно. Смотрите мой ответ ниже, stackoverflow.com/a/36894871/1204556
Монарх Вадия
8

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

const isDOM = el => el instanceof Element
Дамжан Павлица
источник
1
Brilliant! Работает!
Педро Феррейра
6

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

$ npm install lodash.iselement

И в коде:

var isElement = require("lodash.iselement");
isElement(document.body);
mightyiam
источник
1
Мне нравится это решение. Это просто и работает в Edge и IE, даже для элементов в отдельных фреймах, в отличие от большинства решений с наибольшим количеством голосов.
Элиас Замария
Этот ответ полезен, хотя для запуска модулей NPM в браузере потребуется Webpack.
Эдвин Пратт
5

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

if (obj.nodeName){
    switch (obj.nodeType){
    case 1: return 'element';
    case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
    }
}
finpingvin
источник
12
Этот код не утверждает, что объект является элементом DOM; только то, что это выглядит немного как один. Любому объекту могут быть присвоены свойства nodeName и nodeType, которые удовлетворяют этому коду.
Томасруттер
Этот ответ не обнаруживает все типы элементов HTML. Например, элементы SVG не поддерживаются. Смотрите мой ответ ниже.
Монарх Вадия
На самом деле не работает со всеми элементами, например SVG. Смотрите мой ответ ниже, stackoverflow.com/a/36894871/1204556
Монарх Вадия
4

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

Дон П

Дон П
источник
Я протестировал это в последних версиях Chrome и FF, а также в IE11, и это работает везде, в том числе для текстовых узлов и объектов, созданных с помощью document.createElement()DOM, но не вставленных в них. Удивительно (: Спасибо
Geradlus_RU
Это выглядит как достойный ответ, хотя мой делает много того же и менее сложный. stackoverflow.com/a/36894871/1204556
Монарх Вадия
4

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

function isHTMLElement(o) {
    return (o.constructor.toString().search(/\object HTML.+Element/) > -1);
}
зашифровывать
источник
4

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

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

или, как предложил HTMLGuy :

const isDomEntity = entity => {
  return typeof entity   === 'object' && entity.nodeType !== undefined
}
Римский
источник
1
Слишком многословно. Сравнение уже вернет логическое значение:return typeof entity === 'object' && typeof entity.nodeType !== undefined;
HTMLGuy
1
Очень интересно! Иногда, в зависимости от типов, которые у вас есть на ваших objectи / или поперти, это может быть очень удобно! Tx, @Roman
Педро Феррейра
3
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; },

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

Эрих Хорн
источник
obj.constructor.name не работает в IE, потому что в IE функции не имеют свойства name. Заменить на obj.constructor! = Object.
mathheadinclouds
3

Это может быть полезно: 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);
}

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

jherax
источник
Все ложное должно замкнуть ваше логическое значение. undefined && window.spam("should bork")например, никогда не оценивает фальшивую spamфункцию. Так что не !!нужно, я не верю. Что, вы можете предоставить [неакадемический] крайний случай, когда его использование имеет значение?
Ерф
Спасибо за вашу акларацию. Я использовал * !! * двойное отрицание, чтобы преобразовать все выражения в логическое значение, а не в ложь или ложь.
Jherax
Да, но нет никакой практической причины делать это, я не думаю - смотрите здесь . И, конечно же, здесь нет необходимости использовать Short-Cut Eval. Даже если вы не купили !!аргумент « никогда не нужен» ( а если нет, мне любопытно, почему бы и нет ), вы можете отредактировать эту строку return !!(obj && typeof obj === "object" && obj.nodeType === 1 && obj.nodeName);и заставить ее работать так же.
Ерф
Это было то, что я сделал;) более чистый и тот же эффект. Спасибо.
Jherax
2

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

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
timewaster51
источник
3
typeof ({innerHTML: ""}).innerHTML === "string"
Qtax
ГОРЯЧИЙ! Этот ответ должен быть победителем игры. if (typeof obj.innerHTML! == 'string') // не является элементом dom.
user3751385
1
Сначала я отреагировал на критику @Qtax и thomasrutter более ранним ответом , но я начинаю его покупать. Хотя раньше я не сталкивался с кряками, подобными уткам, как это было раньше, я вижу, как кто-то не проверяет, работает ли что-то узел notANode.innerHTML = "<b>Whoops</b>";, а затем, когда этот код передает свой зараженный объект этому коду. Защитный код === лучший код, все остальные вещи равны, и это в конечном итоге не является защитным.
Ерф
2

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

angular.isElement

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

Алвис
источник
Более полезно включить код Angular : function isElement(node) { return !!(node && (node.nodeName || (node.prop && node.attr && node.find))); }выглядит немного как @ finpingvin . Обратите внимание, что он определяет, «является ли ссылка элементом DOM (или обернутым элементом jQuery). »
ruffin
2

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

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

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

if(a.isDomElement){}

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

Догуш Атасой
источник
1
1) не рекомендуется менять объекты, которыми вы не владеете. 2) это не обнаруживает элементы, которые не являются частью одного и того же документа.
Фреганте
2

По словам МДН

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

xianshenglu
источник
1

Я думаю, что вам нужно сделать тщательную проверку некоторых свойств, которые всегда будут в элементе dom, но их комбинация, скорее всего, не будет в другом объекте, например:

var isDom = function (inp) {
    return inp && inp.tagName && inp.nodeName && inp.ownerDocument && inp.removeAttribute;
};
Андреас Греч
источник
1

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

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

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

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

Деннис С
источник
1

Возможно, это альтернатива? Протестировано в 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
Snoozer Man
источник
2
Хорошая попытка, но обработка исключений обходится слишком дорого, если ее можно избежать. Кроме того, ES5 позволяет вам определять свойства только для чтения для объектов.
Энди Э
1

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

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

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

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

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

Сослан
источник
1

отличить необработанный объект js от HTMLElement

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

bortunac
источник
0

вот трюк с использованием JQuery

var obj = {};
var element = document.getElementById('myId'); // or simply $("#myId")

$(obj).html() == undefined // true
$(element).html() == undefined // false

поэтому поместим это в функцию:

function isElement(obj){

   return (typeOf obj === 'object' && !($(obj).html() == undefined));

}
Матус
источник
2
jQuery внутренне делает elem.nodeType === 1так, почему бы не сохранить накладные расходы на вызов и зависимость jQuery и сделать так, чтобы ваша функция isElement сделала это сама?
Джозеф Леннокс,
Это 2016, просто скажи "нет".
Томас МакКейб
0

Не для того, чтобы разобраться с этим или чем-то другим, кроме браузеров, совместимых с ES5, почему бы просто:

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

Не будет работать с TextNodes и не уверен в Shadow DOM, DocumentFragments и т. Д., Но будет работать почти со всеми элементами HTML-тегов.

Трэвис Кауфман
источник
0

Это будет работать практически для любого браузера. (Здесь нет различия между элементами и узлами)

function dom_element_check(element){
    if (typeof element.nodeType !== 'undefined'){
        return true;
    }
    return false;
}
Zv_oDD
источник
Прежде всего, вам не нужно возвращать true или возвращать false, просто верните оператор if. Во-вторых, это вернет истину для {nodeType: 1}
bluejayke
Я склонен использовать чрезмерно подробный код (на этом сайте) с целью сделать код более понятным;)
Zv_oDD
0

Абсолютно правильный метод, check target - это настоящий первичный код HTML-элемента:

    (function (scope) {
        if (!scope.window) {//May not run in window scope
            return;
        }
        var HTMLElement = window.HTMLElement || window.Element|| function() {};

        var tempDiv = document.createElement("div");
        var isChildOf = function(target, parent) {

            if (!target) {
                return false;
            }
            if (parent == null) {
                parent = document.body;
            }
            if (target === parent) {
                return true;
            }
            var newParent = target.parentNode || target.parentElement;
            if (!newParent) {
                return false;
            }
            return isChildOf(newParent, parent);
        }
        /**
         * The dom helper
         */
        var Dom = {
            /**
             * Detect if target element is child element of parent
             * @param {} target The target html node
             * @param {} parent The the parent to check
             * @returns {} 
             */
            IsChildOf: function (target, parent) {
                return isChildOf(target, parent);
            },
            /**
             * Detect target is html element
             * @param {} target The target to check
             * @returns {} True if target is html node
             */
            IsHtmlElement: function (target) {
                if (!X.Dom.IsHtmlNode(target)) {
                    return false;
                }
                return target.nodeType === 1;
            },
            /**
             * Detect target is html node
             * @param {} target The target to check
             * @returns {} True if target is html node
             */
            IsHtmlNode:function(target) {
                if (target instanceof HTMLElement) {
                    return true;
                }
                if (target != null) {
                    if (isChildOf(target, document.documentElement)) {
                        return true;
                    }
                    try {
                        tempDiv.appendChild(target.cloneNode(false));
                        if (tempDiv.childNodes.length > 0) {
                            tempDiv.innerHTML = "";
                            return true;
                        }
                    } catch (e) {

                    }
                }
                return false;
            }
        };
        X.Dom = Dom;
    })(this);

Тест в IE 5

Dexiang
источник
0

Каждый DOMElement.constructor возвращает функцию HTML ... Element () или [Object HTML ... Element], так что ...

function isDOM(getElem){
    if(getElem===null||typeof getElem==="undefined") return false;
    var c = getElem.constructor.toString();
    var html = c.search("HTML")!==-1;
    var element = c.search("Element")!==-1;
    return html&&element;
}
Paweł
источник
0

У меня есть особый способ сделать это, который еще не был упомянут в ответах.

Мое решение основано на четырех тестах. Если объект проходит все четыре, то это элемент:

  1. Объект не является нулевым.

  2. У объекта есть метод с именем "appendChild".

  3. Метод "appendChild" был унаследован от класса Node и является не просто методом-самозванцем (пользовательское свойство с идентичным именем).

  4. Объект имеет тип узла 1 (элемент). Объекты, которые наследуют методы от класса Node , всегда являются узлами, но не обязательно элементами.

В: Как я могу проверить, является ли данное свойство наследуемым, а не просто самозванцем?

A: Простой тест, чтобы увидеть, действительно ли метод унаследован от Node, состоит в том, чтобы сначала убедиться, что свойство имеет тип «объект» или «функция». Затем преобразуйте свойство в строку и проверьте, содержит ли результат текст «[Native Code]». Если результат выглядит примерно так:

function appendChild(){
[Native Code]
}

Затем метод был унаследован от объекта Node. Смотрите https://davidwalsh.name/detect-native-function

И, наконец, объединяя все тесты, решение:

function ObjectIsElement(obj) {
    var IsElem = true;
    if (obj == null) {
        IsElem = false;
    } else if (typeof(obj.appendChild) != "object" && typeof(obj.appendChild) != "function") {
        //IE8 and below returns "object" when getting the type of a function, IE9+ returns "function"
        IsElem = false;
    } else if ((obj.appendChild + '').replace(/[\r\n\t\b\f\v\xC2\xA0\x00-\x1F\x7F-\x9F ]/ig, '').search(/\{\[NativeCode]}$/i) == -1) {
        IsElem = false;
    } else if (obj.nodeType != 1) {
        IsElem = false;
    }
    return IsElem;
}
user3163495
источник
0
(element instanceof $ && element.get(0) instanceof Element) || element instanceof Element

Это будет проверять, даже если это элемент DOM JQuery или JavaScript

Арджун Каккар
источник
0

Единственный способ гарантировать, что вы проверяете фактический элемент HTMLEement, а не просто объект с теми же свойствами, что и элемент HTML, - это определить, наследуется ли он от Node, поскольку невозможно создать новый Node () в JavaScript. (если только нативная функция Node не будет перезаписана, но тогда вам не повезет). Так:

function isHTML(obj) {
    return obj instanceof Node;
}

console.log(
  isHTML(test),
  isHTML(ok),
  isHTML(p),
  isHTML(o),
  isHTML({
    constructor: {
      name: "HTML"
    }
  }),
  isHTML({
    __proto__: {
      __proto__: {
        __proto__: {
          __proto__: {
            constructor: {
              constructor: { 
                name: "Function"
                
              },
              name: "Node"
            }
          }
        }
      }
    }
  }),
)
<div id=test></div>
<blockquote id="ok"></blockquote>
<p id=p></p>
<br id=o>
<!--think of anything else you want--!>

bluejayke
источник