Come si controlla se un oggetto JavaScript è un oggetto DOM?


248

Sto cercando di ottenere:

document.createElement('div')  //=> true
{tagName: 'foobar something'}  //=> false

Nei miei script, lo usavo solo perché non avevo mai avuto bisogno tagNamedi una proprietà:

if (!object.tagName) throw ...;

Quindi, per il secondo oggetto, ho trovato quanto segue come soluzione rapida, che per lo più funziona. ;)

Il problema è che dipende dai browser che applicano proprietà di sola lettura, cosa che non tutti fanno.

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

C'è un buon sostituto?


3
Sono ottuso nel chiedermi se un "oggetto DOM" non dovrebbe coprire non solo gli elementi ma anche tutti i nodi (nodi di testo, attributi, ecc.)? Tutte le risposte e il modo in cui hai posto la domanda tendono a suggerire che questa domanda riguardi specificamente Elements ...
mike rodent,

Risposte:


300

Questo potrebbe essere di interesse:

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

Fa parte del DOM, Level2 .

Aggiornamento 2 : è così che l'ho implementato nella mia libreria: (il codice precedente non funzionava in Chrome, perché Node e HTMLElement sono funzioni anziché l'oggetto previsto. Questo codice è testato in FF3, IE7, Chrome 1 e 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
Vale la pena notare che questo non funzionerà su elementi che appartengono ad altre finestre / frame. La tipizzazione di anatre è l'approccio raccomandato
Andy E

2
Puoi ingannarlo con:function Fake() {}; Fake.prototype=document.createElement("div"); alert(new Fake() instanceof HTMLElement);
Kernel James,

11
WTF fatto: Firefox 5 e precedenti di ritorno trueper [] instanceof HTMLElement.
Rob W

6
A proposito, HTMLElementè sempre un function, quindi typeofti getterà fuori pista e eseguirà la seconda parte dell'istruzione. Puoi provare se lo desideri instanceof Object, perché la funzione sarà un'istanza di Object, o semplicemente verificherà esplicitamente typeof === "function", perché Nodee HTMLElementsono entrambe le funzioni degli oggetti nativi.
Roland,

2
Quando chiami isElement(0), restituisce 0, non falso ... Perché è così e come posso impedirlo?
Jessica,

68

Il seguente codice semplicissimo compatibile con IE8 funziona perfettamente.

La risposta accettata non rileva tutti i tipi di elementi HTML. Ad esempio, gli elementi SVG non sono supportati. Al contrario, questa risposta funziona per HTML e SVG.

Guardalo in azione qui: https://jsfiddle.net/eLuhbu6r/

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

3
'Element' non è definito su IE7
Dan,

49
Sono dell'opinione che chiunque stia ancora utilizzando IE7 dovrebbe impiegare i cinque secondi per scaricare un browser migliore invece di utilizzarlo per investire giorni o settimane aggirando il proprio rifiuto di rimanere al passo con i tempi.
mopsyd,

1
Sono d'accordo con @mopsyd, ma l'autore della risposta afferma che funziona in IE7, che potrebbe essere necessario aggiornare per motivi di correttezza.
Lajos Meszaros,

1
Aggiornato per dire IE9. Non sono sicuro che IE8 lo supporti.
Monarch Wadia,

1
@MonarchWadia sì, è supportato in IE8. Ma nota che questo non restituisce true per documentelement (in tutti i browser). se ne hai bisogno, dovresti provare:x instanceof Element || x instanceof HTMLDocument
S. Serpooshan

11

Tutte le soluzioni sopra e sotto (compresa la mia soluzione) soffrono della possibilità di essere errate, specialmente su IE - è del tutto possibile (ri) definire alcuni oggetti / metodi / proprietà per imitare un nodo DOM che rende il test non valido.

Quindi di solito uso i test in stile tipografia: eseguo dei test specifici per le cose che uso. Ad esempio, se voglio clonare un nodo, lo collaudo in questo modo:

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

Fondamentalmente è un piccolo controllo di integrità + il test diretto per un metodo (o una proprietà) che sto pianificando di utilizzare.

Per inciso, il test sopra è un buon test per i nodi DOM su tutti i browser. Ma se vuoi essere al sicuro controlla sempre la presenza di metodi e proprietà e verificane i tipi.

EDIT: IE utilizza gli oggetti ActiveX per rappresentare i nodi, quindi le loro proprietà non si comportano come veri oggetti JavaScript, ad esempio:

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

mentre dovrebbe restituire "funzione" e truerispettivamente. L'unico modo per testare i metodi è vedere se sono definiti.


"typeof document.body.cloneNode" restituisce "object" nel mio IE
Dennis C

Questa sembra una risposta decente. Vedi comunque la mia risposta qui sotto, stackoverflow.com/a/36894871/1204556
Monarch Wadia

8

Potresti provare ad aggiungerlo a un vero nodo DOM ...

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

    return true;
}

11
funziona? È ancora una soluzione. Creativo.
Justin Meyer,

3
+1 per la creatività e la certezza che offre. Tuttavia, se il nodo fa già parte del DOM, l'hai appena rimosso! Quindi ... questa risposta è incompleta senza fare il lavoro per aggiungere nuovamente l'elemento al DOM, se necessario.
svidgen,

4
Sto leggendo questo dopo quasi 5 anni e penso che sia uno dei più belli. Deve solo essere raffinato. Ad esempio, puoi provare ad aggiungere un clone del nodo a un elemento separato. Se questo non è un oggetto DOM. qualcosa andrà sicuramente storto. Tuttavia, è ancora una soluzione piuttosto costosa.
MaxArt,

O invece di cercare di aggiungere il clone dell'elemento, solo cercando di clonarlo dovrebbe essere sufficiente: obj.cloneNode(false). E non ha effetti collaterali.
mauroc8,

1
Questo è davvero costoso e inutilmente complicato. Vedi la mia risposta di seguito, stackoverflow.com/a/36894871/1204556
Monarch Wadia


6

Che ne dici di Lo-Dash_.isElement ?

$ npm install lodash.iselement

E nel codice:

var isElement = require("lodash.iselement");
isElement(document.body);

1
Mi piace questa soluzione. È semplice e funziona in Edge e IE, anche per elementi in iframe separati, a differenza della maggior parte delle soluzioni più votate qui.
Elias Zamaria,

Questa risposta è utile, sebbene sia necessario Webpack per eseguire i moduli NPM nel browser.
Edwin Pratt,

5

Questo è dalla deliziosa libreria JavaScript MooTools :

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

12
Questo codice non afferma che l'oggetto sia un elemento DOM; solo che sembra un po 'come uno. A qualsiasi oggetto è possibile assegnare una proprietà nodeName e nodeType e soddisfare questo codice.
thomasrutter,

Questa risposta non rileva tutti i tipi di elementi HTML. Ad esempio, gli elementi SVG non sono supportati. Vedi la mia risposta qui sotto.
Monarch Wadia,

Non funziona davvero su tutti gli elementi, ad esempio SVG. Vedi la mia risposta di seguito, stackoverflow.com/a/36894871/1204556
Monarch Wadia

4

Usando il rilevamento di root trovato qui , possiamo determinare se ad esempio alert è un membro della radice dell'oggetto, che è quindi probabile che sia una finestra:

function isInAnyDOM(o) { 
  return (o !== null) && !!(o.ownerDocument && (o.ownerDocument.defaultView || o.ownerDocument.parentWindow).alert); // true|false
}

Per determinare se l'oggetto è la finestra corrente è ancora più semplice:

function isInCurrentDOM(o) { 
  return (o !== null) && !!o.ownerDocument && (window === (o.ownerDocument.defaultView || o.ownerDocument.parentWindow)); // true|false
}

Questo sembra essere meno costoso della soluzione try / catch nel thread di apertura.

Don P


L'ho provato negli ultimi Chrome e FF, e anche in IE11, e funziona ovunque, anche per nodi di testo e oggetti creati tramite document.createElement()ma non inseriti anche in DOM. Incredibile (: grazie
Geradlus_RU

Sembra una risposta decente, anche se la mia fa molte delle stesse cose ed è meno complicata. stackoverflow.com/a/36894871/1204556
Monarch Wadia

4

vecchio thread, ma ecco una possibilità aggiornata per gli utenti ie8 e ff3.5 :

function isHTMLElement(o) {
    return (o.constructor.toString().search(/\object HTML.+Element/) > -1);
}

4

Suggerisco un modo semplice per verificare se una variabile è un elemento DOM

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

o come suggerito da HTMLGuy :

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

1
Troppo prolisso. Il confronto restituirà già un valore booleano:return typeof entity === 'object' && typeof entity.nodeType !== undefined;
HTML Acquista

1
Molto interessante! A volte, a seconda dei tipi che hai sul tuo objects e / o poperties, questo può essere molto utile! Tx, @Roman
Pedro Ferreira,

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

// In effetti, è più probabile che io usi questi in linea, ma a volte è bene avere queste scorciatoie per il codice di installazione


obj.constructor.name non funziona in IE, perché in IE le funzioni non hanno la proprietà name. Sostituisci con obj.constructor! = Object.
matematica include

3

Questo potrebbe essere utile: 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);
}

Nel codice sopra, utilizziamo l' operatore doppia negazione per ottenere il valore booleano dell'oggetto passato come argomento, in questo modo assicuriamo che ogni espressione valutata nell'istruzione condizionale sia booleana, sfruttando la valutazione del cortocircuito , quindi la funzione ritorna trueofalse


Qualsiasi cosa falsa dovrebbe cortocircuitare il tuo booleano. undefined && window.spam("should bork")non valuta mai la spamfunzione falsa , per esempio. Quindi non è !!necessario, non ci credo. Che, puoi fornire un caso limite [non accademico] in cui il suo uso è importante?
ruffin,

Grazie per la tua dichiarazione. Ho usato * !! * doppia negazione per convertire tutte le espressioni in valore booleano, non verità o falsità.
jherax,

Giusto, ma non c'è motivo pratico per farlo, non credo - vedi qui . E non è certamente necessario approfittare di Short-cut eval qui. Anche se non hai acquistato l' !!argomento "non è mai necessario" ( e se non lo fai, sono curioso perché no ), puoi modificare quella linea return !!(obj && typeof obj === "object" && obj.nodeType === 1 && obj.nodeName);e farla funzionare allo stesso modo.
ruffin,

Questo è quello che ho fatto;) più pulito e stesso effetto. grazie.
jherax,

2

Puoi vedere se l'oggetto o il nodo in questione restituisce un tipo di stringa.

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

3
typeof ({innerHTML: ""}).innerHTML === "string"
Qtax

CALDO! Questa risposta dovrebbe essere il vincitore del gioco. if (typeof obj.innerHTML! == 'string') // non un elemento dom.
user3751385

1
Inizialmente ho reagito alla critica di @Qtax e thomasrutter su una risposta precedente , ma sto iniziando a comprarlo. Sebbene non mi sia mai imbattuto in cani che tremano come anatre esattamente come prima, posso vedere qualcuno che non controlla se qualcosa è un nodo, in esecuzione notANode.innerHTML = "<b>Whoops</b>";, quindi in seguito avere quel codice passa il suo oggetto contaminato a questo codice. Codice difensivo === codice migliore, tutte le altre cose uguali, e questo alla fine non è difensivo.
ruffin,


2

Penso che la prototipazione non sia un'ottima soluzione, ma forse questa è la più veloce: definire questo blocco di codice;

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

di controllare la proprietà isDomElement degli oggetti:

if(a.isDomElement){}

Spero che aiuti.


1
1) non è consigliabile cambiare oggetti che non possiedi. 2) questo non rileva elementi che non fanno parte dello stesso documento.
fregante,

2

Secondo mdn

Elementè la classe base più generale da cui tutti gli oggetti in Documentun'eredità. Ha solo metodi e proprietà comuni a tutti i tipi di elementi.

Siamo in grado di implementare isElementper prototipo. Ecco il mio consiglio:

/**
 * @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


1

Penso che ciò che devi fare sia verificare attentamente alcune proprietà che saranno sempre presenti in un elemento dom, ma la loro combinazione non sarà molto probabilmente in un altro oggetto, in questo modo:

var isDom = function (inp) {
    return inp && inp.tagName && inp.nodeName && inp.ownerDocument && inp.removeAttribute;
};

1

In Firefox, puoi usare il instanceof Node. Questo Nodeè definito in DOM1 .

Ma non è così facile in IE.

  1. "instanceof ActiveXObject" può solo dire che è un oggetto nativo.
  2. "typeof document.body.appendChild == 'object'" indica che potrebbe essere un oggetto DOM, ma può anche avere qualcos'altro che ha la stessa funzione.

Puoi solo assicurarti che sia un elemento DOM usando la funzione DOM e catturare eventuali eccezioni. Tuttavia, potrebbe avere effetti collaterali (ad es. Modifica dello stato interno / prestazioni / perdita di memoria)


1

Forse questa è un'alternativa? Testato su Opera 11, FireFox 6, Internet Explorer 8, Safari 5 e 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;
}

Ad esempio, questa funzione non verrà ingannata

isDOMNode( {'nodeName':'fake'} ); // returns false

2
Buona prova, ma la gestione delle eccezioni è un costo troppo costoso se può essere evitata. Inoltre, ES5 consente di definire proprietà di sola lettura per gli oggetti.
Andy E

1

Questo è quello che ho capito:

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

Per migliorare le prestazioni ho creato una funzione auto-invocante che verifica le funzionalità del browser una sola volta e assegna la funzione appropriata di conseguenza.

Il primo test dovrebbe funzionare nella maggior parte dei browser moderni ed è già stato discusso qui. Verifica solo se l'elemento è un'istanza di HTMLElement. Molto semplice.

Il secondo è il più interessante. Questa è la sua funzionalità principale:

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

Verifica se el è un'istanza del costruttore che finge di essere. Per fare ciò, abbiamo bisogno dell'accesso al contruttore di un elemento. Ecco perché lo stiamo testando nell'istruzione if. IE7 ad esempio non riesce, perché (document.createElement("a")).constructorè undefinedin IE7.

Il problema con questo approccio è che in document.createElementrealtà non è la funzione più veloce e potrebbe facilmente rallentare l'applicazione se stai testando molti elementi con essa. Per risolvere questo, ho deciso di mettere in cache i costruttori. L'oggetto ElementConstructorsha nodeNames come chiavi con i suoi corrispondenti costruttori come valori. Se un costruttore è già memorizzato nella cache, lo utilizza dalla cache, altrimenti crea l'Elemento, memorizza nella cache il costruttore per un accesso futuro e quindi esegue il test su di esso.

Il terzo test è lo spiacevole fallback. Verifica se el è un object, ha una nodeTypeproprietà impostata su 1e una stringa come nodeName. Questo non è molto affidabile, ovviamente, ma la stragrande maggioranza degli utenti non dovrebbe nemmeno fare un passo indietro.

Questo è l'approccio più affidabile che mi è venuto in mente mantenendo le prestazioni il più alto possibile.


1

Verifica se objeredita dal nodo .

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

Il nodo è un semplice interfaccia da cui HTMLElement ed ereditare testo.


1

differenziare un oggetto js non elaborato da un HTMLElement

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

uso:

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

// O

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

uso:

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


0

ecco un trucco usando jQuery

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

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

quindi mettendolo in una funzione:

function isElement(obj){

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

}

2
jQuery lo sta facendo internamente elem.nodeType === 1, perché non salvare l'overhead della chiamata e la dipendenza jQuery e la tua funzione isElement lo fa da sola?
Joseph Lennox,

È il 2016, basta dire "no".
Thomas McCabe,

0

Non per battere su questo o altro, ma per i browser conformi a ES5 perché non solo:

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

Non funziona su TextNodes e non sono sicuro di Ombra DOM o DocumentFragments ecc, ma sarà lavorare su quasi tutti gli elementi di tag HTML.


0

Funzionerà con quasi tutti i browser. (Nessuna distinzione tra elementi e nodi qui)

function dom_element_check(element){
    if (typeof element.nodeType !== 'undefined'){
        return true;
    }
    return false;
}

prima di tutto, non è necessario restituire true o restituire false, è sufficiente restituire l'istruzione if. In secondo luogo, questo tornerà vero per {nodeType: 1}
bluejayke il

Tendo a usare un codice eccessivamente dettagliato (su questo sito) allo scopo di rendere più chiara l'intenzione del codice;)
Zv_oDD

0

Un metodo assolutamente corretto, controllare target è un vero codice primario elemento 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);

Test in IE 5


0

Ogni DOMElement.constructor restituisce la funzione HTML ... Element () o [Object HTML ... Element] quindi ...

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

0

Ho un modo speciale per farlo che non è stato ancora menzionato nelle risposte.

La mia soluzione si basa su quattro test. Se l'oggetto supera tutti e quattro, allora è un elemento:

  1. L'oggetto non è nullo.

  2. L'oggetto ha un metodo chiamato "appendChild".

  3. Il metodo "appendChild" è stato ereditato dalla classe Node e non è solo un metodo impostore (una proprietà creata dall'utente con un nome identico).

  4. L'oggetto è di tipo nodo 1 (elemento). Gli oggetti che ereditano i metodi dalla classe Node sono sempre Nodi, ma non necessariamente Elementi.

D: Come posso verificare se una determinata proprietà è ereditata e non è solo un impostore?

A: Un semplice test per vedere se un metodo è stato veramente ereditato da Node è verificare innanzitutto che la proprietà abbia un tipo di "oggetto" o "funzione". Successivamente, converti la proprietà in una stringa e controlla se il risultato contiene il testo "[Native Code]". Se il risultato è simile al seguente:

function appendChild(){
[Native Code]
}

Quindi il metodo è stato ereditato dall'oggetto Node. Vedi https://davidwalsh.name/detect-native-function

E infine, riunendo tutti i test, la soluzione è:

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

0
(element instanceof $ && element.get(0) instanceof Element) || element instanceof Element

Questo verificherà anche se si tratta di un elemento DOM jQuery o JavaScript


0

L'unico modo per garantire che stai controllando un HTMLEement reale, e non solo un oggetto con le stesse proprietà di un elemento HTML, è determinare se eredita da Node, poiché è impossibile creare un nuovo Node () in JavaScript. (a meno che la funzione Nodo nativa non venga sovrascritta, ma poi sei sfortunato). Così:

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--!>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.