Bagaimana Anda memeriksa apakah Obyek JavaScript adalah Obyek DOM?

247

Saya mencoba untuk mendapatkan:

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

Dalam skrip saya sendiri, saya biasa menggunakan ini karena saya tidak pernah membutuhkan tagNamesebagai properti:

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

Jadi untuk objek kedua, saya datang dengan yang berikut sebagai solusi cepat - yang kebanyakan berhasil. ;)

Masalahnya adalah, itu tergantung pada browser yang memberlakukan properti read-only, yang tidak semuanya melakukannya.

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

Apakah ada pengganti yang bagus?

Jonathan Lonowski
sumber
3
Apakah saya menjadi bingung ketika bertanya-tanya apakah "Objek DOM" seharusnya tidak hanya mencakup Elemen tetapi juga semua Node (Node teks, Atribut, dll.)? Semua jawaban dan cara Anda mengajukan pertanyaan cenderung menyarankan pertanyaan ini secara khusus tentang Elemen ...
mike rodent

Jawaban:

300

Ini mungkin menarik:

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

Itu bagian dari DOM, Level2 .

Pembaruan 2 : Ini adalah cara saya menerapkannya di perpustakaan saya sendiri: (kode sebelumnya tidak berfungsi di Chrome, karena Node dan HTMLElement adalah fungsi alih-alih objek yang diharapkan. Kode ini diuji dalam FF3, IE7, Chrome 1 dan 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"
);
}
beberapa
sumber
11
Perlu dicatat bahwa ini tidak akan bekerja pada elemen yang dimiliki jendela / bingkai lain. Mengetik bebek adalah pendekatan yang disarankan
Andy E
2
Anda dapat membodohinya dengan:function Fake() {}; Fake.prototype=document.createElement("div"); alert(new Fake() instanceof HTMLElement);
Kernel James
11
Fakta WTF: Firefox 5 dan sebelumnya kembali trueuntuk [] instanceof HTMLElement.
Rob W
6
Btw, HTMLElementselalu a function, jadi typeofakan membuat Anda keluar jalur dan akan menjalankan bagian kedua dari pernyataan itu. Anda dapat mencoba jika Anda mau instanceof Object, karena fungsi akan menjadi instance Object, atau hanya memeriksa secara eksplisit typeof === "function", karena Nodedan HTMLElementkeduanya fungsi objek asli.
Roland
2
Ketika Anda menelepon isElement(0), ia mengembalikan 0, bukan salah ... Mengapa begitu, dan bagaimana saya bisa mencegahnya?
Jessica
68

Kompatibel dengan IE8 berikut, kode super sederhana bekerja dengan sempurna.

The jawaban yang diterima tidak mendeteksi semua jenis elemen HTML. Misalnya, elemen SVG tidak didukung. Sebaliknya, jawaban ini berfungsi untuk HTML dan juga SVG.

Lihat beraksi di sini: https://jsfiddle.net/eLuhbu6r/

function isElement(element) {
    return element instanceof Element || element instanceof HTMLDocument;  
}
Raja Wadia
sumber
3
'Elemen' tidak didefinisikan pada IE7
Dan
49
Saya berpendapat bahwa siapa pun yang masih menggunakan IE7 harus menghabiskan lima detik untuk mengunduh peramban yang lebih baik daripada menaruhnya pada kami untuk berinvestasi berhari-hari atau berminggu-minggu untuk mengatasi penolakan mereka.
mopsyd
1
Saya setuju dengan @mopsyd, tetapi penulis jawaban menyatakan, bahwa ia berfungsi di IE7, yang mungkin perlu diperbarui demi kebenaran.
Lajos Meszaros
1
Diperbarui mengatakan IE9. Saya tidak yakin apakah IE8 mendukungnya.
Monarch Wadia
1
@ MonarchWadia ya itu didukung di IE8. Tetapi perhatikan bahwa ini tidak mengembalikan true untuk documentelemen (di semua browser). jika Anda membutuhkannya, Anda harus mencoba:x instanceof Element || x instanceof HTMLDocument
S.Serpooshan
11

Semua solusi di atas dan di bawah (termasuk solusi saya) menderita kemungkinan salah, terutama pada IE - sangat mungkin untuk (kembali) mendefinisikan beberapa objek / metode / properti untuk meniru node DOM yang membuat tes tidak valid.

Jadi biasanya saya menggunakan pengujian gaya mengetik bebek: Saya menguji secara khusus untuk hal-hal yang saya gunakan. Sebagai contoh, jika saya ingin mengkloning sebuah node saya mengujinya seperti ini:

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

Pada dasarnya ini adalah pemeriksaan kewarasan kecil + tes langsung untuk suatu metode (atau properti) yang saya rencanakan untuk digunakan.

Kebetulan tes di atas adalah tes yang baik untuk node DOM di semua browser. Tetapi jika Anda ingin berada di sisi yang aman selalu periksa keberadaan metode dan properti dan verifikasi tipenya.

EDIT: IE menggunakan objek ActiveX untuk mewakili node, jadi propertinya tidak berperilaku sebagai objek JavaScript yang sebenarnya, misalnya:

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

sementara itu harus mengembalikan "fungsi" dan truemasing - masing. Satu-satunya cara untuk menguji metode adalah untuk melihat apakah sudah ditentukan.

Eugene Lazutkin
sumber
"typeof document.body.cloneNode" tidak mengembalikan "objek" di IE saya
Dennis C
Ini sepertinya jawaban yang layak. Lihat jawaban saya di bawah ini, stackoverflow.com/a/36894871/1204556
Monarch Wadia
8

Anda dapat mencoba menambahkannya ke simpul DOM nyata ...

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

    return true;
}
Greg
sumber
11
Apakah ini berhasil? Itu masih solusi. Yang kreatif pada saat itu.
Justin Meyer
3
+1 untuk kreativitas dan kepastian penawaran ini. Namun, jika simpul sudah menjadi bagian dari DOM, Anda baru saja menghapusnya! Jadi ... jawaban ini tidak lengkap tanpa melakukan pekerjaan untuk menambahkan kembali elemen ke DOM jika perlu.
svidgen
4
Saya membaca ini setelah hampir 5 tahun, dan saya pikir ini salah satu yang paling keren. Itu hanya perlu disempurnakan. Anda dapat mencoba menambahkan klon simpul ke elemen terpisah, misalnya. Jika itu bukan objek DOM. sesuatu pasti akan salah. Meski begitu, masih merupakan solusi yang mahal.
MaxArt
Atau alih-alih mencoba untuk menambahkan clone elemen, hanya mencoba untuk mengkloning itu harus cukup: obj.cloneNode(false). DAN tidak memiliki efek samping.
mauroc8
1
Ini sangat mahal dan tidak perlu rumit. Lihat jawaban saya di bawah, stackoverflow.com/a/36894871/1204556
Monarch Wadia
7

Tidak perlu melakukan peretasan, Anda bisa bertanya apakah sebuah elemen adalah turunan dari Elemen DOM :

const isDOM = el => el instanceof Element
Damjan Pavlica
sumber
1
Cemerlang! Bekerja!
Pedro Ferreira
6

Bagaimana dengan Lo-Dash_.isElement ?

$ npm install lodash.iselement

Dan dalam kode:

var isElement = require("lodash.iselement");
isElement(document.body);
perkasa
sumber
1
Saya suka solusi ini. Ini sederhana, dan bekerja di Edge dan IE, bahkan untuk elemen-elemen dalam iframe yang terpisah, tidak seperti sebagian besar solusi pilihan tertinggi di sini.
Elias Zamaria
Jawaban ini sangat membantu, meskipun orang perlu Webpack untuk menjalankan modul NPM di browser.
Edwin Pratt
5

Ini dari pustaka JavaScript yang indah MooTools :

if (obj.nodeName){
    switch (obj.nodeType){
    case 1: return 'element';
    case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
    }
}
finpingvin
sumber
12
Kode ini tidak menyatakan bahwa objek adalah elemen DOM; hanya saja tampilannya sedikit mirip satu. Objek apa pun dapat diberi properti nodeName dan nodeType dan memenuhi kode ini.
thomasrutter
Jawaban ini tidak mendeteksi semua jenis elemen HTML. Misalnya, elemen SVG tidak didukung. Lihat jawaban saya di bawah ini.
Monarch Wadia
Tidak benar-benar berfungsi pada semua elemen, misalnya SVG. Lihat jawaban saya di bawah, stackoverflow.com/a/36894871/1204556
Monarch Wadia
4

Dengan menggunakan deteksi root yang ditemukan di sini , kita dapat menentukan apakah mis. Lansiran adalah anggota dari root objek, yang kemudian kemungkinan akan berupa jendela:

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

Untuk menentukan apakah objeknya adalah jendela saat ini lebih sederhana:

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

Ini tampaknya lebih murah daripada solusi coba / tangkap di utas pembuka.

Don P

Don P
sumber
Saya sudah menguji ini di Chrome dan FF terbaru, dan juga di IE11, dan itu bekerja di mana-mana, juga untuk node teks dan objek yang dibuat melalui document.createElement()tetapi tidak dimasukkan dalam DOM juga. Luar biasa (: Terima kasih
Geradlus_RU
Ini terlihat seperti jawaban yang layak, meskipun saya melakukan banyak hal yang sama dan tidak terlalu rumit. stackoverflow.com/a/36894871/1204556
Monarch Wadia
4

utas lama, tapi di sini ada kemungkinan yang diperbarui untuk pengguna ie8 dan ff3.5 :

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

Saya menyarankan cara sederhana untuk menguji apakah suatu variabel adalah elemen DOM

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

atau seperti yang disarankan HTMLGuy :

const isDomEntity = entity => {
  return typeof entity   === 'object' && entity.nodeType !== undefined
}
Roma
sumber
1
Terlalu bertele-tele. Perbandingan sudah akan menghasilkan boolean:return typeof entity === 'object' && typeof entity.nodeType !== undefined;
HTMLGuy
1
Sangat menarik! Terkadang, tergantung pada Jenis yang Anda miliki di properti Anda objectdan / atau poperties, ini bisa sangat berguna! 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; },

// Sebenarnya saya lebih cenderung menggunakan inline ini, tetapi kadang-kadang ada baiknya menggunakan pintasan ini untuk kode pengaturan

Erich Horn
sumber
obj.constructor.name tidak berfungsi di IE, karena di IE, fungsi tidak memiliki properti nama. Ganti dengan obj.constructor! = Obyek.
mathheadinclouds
3

Ini bisa membantu: 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);
}

Dalam kode di atas, kami menggunakan operator negasi ganda untuk mendapatkan nilai boolean dari objek yang dilewatkan sebagai argumen, dengan cara ini kami memastikan bahwa setiap ekspresi yang dievaluasi dalam pernyataan bersyarat menjadi boolean, mengambil keuntungan dari Evaluasi Sirkuit Pendek , dengan demikian fungsinya mengembalikan trueataufalse

jherax
sumber
Apa pun yang palsu harus membuat arus pendek boolean Anda. undefined && window.spam("should bork")tidak pernah mengevaluasi spamfungsi palsu , misalnya. Jadi tidak !!perlu, saya tidak percaya. Itu, bisakah Anda memberikan kasus tepi [non-akademik] di mana penggunaannya penting?
ruffin
Terima kasih atas pernyataan Anda. Saya menggunakan * !! * negasi ganda untuk mengubah semua ekspresi menjadi nilai boolean, tidak benar atau salah.
jherax
Benar, tapi tidak ada alasan praktis untuk melakukannya, saya tidak berpikir - lihat di sini . Dan tentu saja tidak perlu mengambil keuntungan dari Short-Cut eval di sini. Bahkan jika Anda tidak membeli !!argumen "tidak pernah dibutuhkan" ( dan jika tidak, saya ingin tahu kenapa tidak ), Anda dapat mengedit baris itu return !!(obj && typeof obj === "object" && obj.nodeType === 1 && obj.nodeName);dan mengoperasikannya juga.
ruffin
Itulah yang saya lakukan;) efeknya lebih bersih dan sama. Terima kasih.
jherax
2

Anda dapat melihat apakah objek atau simpul yang dimaksud mengembalikan tipe string.

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
sumber
3
typeof ({innerHTML: ""}).innerHTML === "string"
Qtax
PANAS! Respons ini harus menjadi pemenang game. if (typeof obj.innerHTML! == 'string') // bukan elemen dom.
user3751385
1
Saya awalnya bereaksi terhadap kritik @Qtax dan thomasrutter pada jawaban sebelumnya , tapi saya mulai membelinya. Meskipun saya belum pernah bertemu dengan anjing-anjing yang sedang meniduri bebek seperti ini sebelumnya, saya dapat melihat seseorang tidak memeriksa apakah ada simpul, sedang berlari notANode.innerHTML = "<b>Whoops</b>";, lalu kemudian kode itu meneruskan objek yang terkontaminasi ke kode ini . Kode defensif === kode yang lebih baik, semua hal lainnya sama, dan ini pada akhirnya tidak defensif.
ruffin
2

Untuk yang menggunakan Angular:

angular.isElement

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

Alvis
sumber
Lebih berguna untuk memasukkan kode Angular : function isElement(node) { return !!(node && (node.nodeName || (node.prop && node.attr && node.find))); }Sepertinya sedikit seperti @ finpingvin . Perhatikan bahwa ini menentukan " apakah referensi adalah elemen DOM (atau elemen jQuery yang dibungkus). "
ruffin
2

Saya pikir prototyping bukan solusi yang sangat bagus tapi mungkin ini yang tercepat: Tentukan blok kode ini;

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

daripada memeriksa objek Anda properti isDomElement:

if(a.isDomElement){}

Saya harap ini membantu.

Doğuş Atasoy
sumber
1
1) mengubah objek yang bukan milik Anda tidak disarankan. 2) ini tidak mendeteksi elemen yang bukan bagian dari dokumen yang sama.
fregante
2

Menurut mdn

Elementadalah kelas dasar paling umum dari mana semua objek dalam suatu Documentwarisan. Hanya memiliki metode dan properti yang umum untuk semua jenis elemen.

Kita dapat mengimplementasikannya isElementdengan prototipe. Ini saran saya:

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

Saya pikir apa yang harus Anda lakukan adalah melakukan pemeriksaan menyeluruh atas beberapa properti yang akan selalu berada dalam elemen dom, tetapi kombinasinya kemungkinan besar tidak akan ada di objek lain, seperti:

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

Di Firefox, Anda dapat menggunakan instanceof Node. Itu Nodedidefinisikan dalam DOM1 .

Tapi itu tidak semudah itu di IE.

  1. "instanceof ActiveXObject" hanya dapat mengatakan bahwa itu adalah objek asli.
  2. "typeof document.body.appendChild == 'object'" mengatakan bahwa itu mungkin objek DOM, tetapi juga bisa menjadi sesuatu yang lain memiliki fungsi yang sama.

Anda hanya dapat memastikan itu adalah elemen DOM dengan menggunakan fungsi DOM dan menangkap jika ada pengecualian. Namun, itu mungkin memiliki efek samping (misalnya mengubah keadaan internal objek / kinerja / kebocoran memori)

Dennis C
sumber
1

Mungkin ini alternatif? Diuji di Opera 11, FireFox 6, Internet Explorer 8, Safari 5 dan 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;
}

Fungsi tidak akan tertipu oleh misal ini

isDOMNode( {'nodeName':'fake'} ); // returns false
Snoozer Man
sumber
2
Selamat mencoba, tetapi penanganan pengecualian merupakan biaya yang terlalu mahal jika dapat dihindari. Juga, ES5 memungkinkan Anda untuk mendefinisikan properti read-only untuk objek.
Andy E
1

Inilah yang saya tahu:

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

Untuk meningkatkan kinerja, saya membuat fungsi self-invaging yang menguji kemampuan browser hanya sekali dan menetapkan fungsi yang sesuai.

Tes pertama harus bekerja di sebagian besar browser modern dan sudah dibahas di sini. Itu hanya menguji apakah elemen tersebut adalah instance dari HTMLElement. Sangat mudah.

Yang kedua adalah yang paling menarik. Ini adalah fungsionalitas intinya:

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

Ia menguji apakah el adalah turunan dari konstruktor yang dikehendaki. Untuk melakukan itu, kita perlu akses ke konstruktor elemen. Itu sebabnya kami menguji ini di if-Statement. IE7 misalnya gagal ini, karena (document.createElement("a")).constructorada undefineddi IE7.

Masalah dengan pendekatan ini adalah yang document.createElementbenar-benar bukan fungsi tercepat dan dapat dengan mudah memperlambat aplikasi Anda jika Anda menguji banyak elemen dengannya. Untuk mengatasi ini, saya memutuskan untuk membuat cache konstruktor. Objek ElementConstructorsmemiliki nodeNames sebagai kunci dengan konstruktor yang sesuai sebagai nilai. Jika sebuah konstruktor sudah di-cache, ia menggunakannya dari cache, jika tidak ia menciptakan Elemen, cache konstruktornya untuk akses di masa depan dan kemudian mengujinya.

Tes ketiga adalah fallback yang tidak menyenangkan. Ia menguji apakah el adalah sebuah object, memiliki nodeTypeproperti yang disetel 1dan string sebagai nodeName. Ini tentu saja tidak terlalu andal, namun sebagian besar pengguna seharusnya tidak mundur sejauh ini.

Ini adalah pendekatan yang paling dapat diandalkan yang saya buat dengan tetap menjaga kinerja setinggi mungkin.

Oliver Sartun
sumber
1

Tes jika objmewarisi dari Node .

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

Node adalah antarmuka dasar dari mana HTMLElement dan Teks mewarisi.

soslan
sumber
1

membedakan objek js mentah dari HTMLElement

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

menggunakan:

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

// ATAU

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

menggunakan:

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

bortunac
sumber
0

inilah trik menggunakan jQuery

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

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

jadi memasukkannya ke dalam fungsi:

function isElement(obj){

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

}
Matus
sumber
2
jQuery secara internal melakukannya, elem.nodeType === 1mengapa tidak menyimpan overhead panggilan dan ketergantungan jQuery dan apakah fungsi isElement Anda melakukannya sendiri?
Joseph Lennox
Ini tahun 2016, katakan saja "tidak".
Thomas McCabe
0

Bukan untuk menekankan ini atau apa pun kecuali untuk browser yang sesuai dengan ES5 mengapa tidak hanya:

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

Tidak akan bekerja pada TextNodes dan tidak yakin tentang Shadow DOM atau DocumentFragments dll. Tetapi akan bekerja pada hampir semua elemen tag HTML.

Travis Kaufman
sumber
0

Ini akan berfungsi untuk hampir semua browser. (Tidak ada perbedaan antara elemen dan node di sini)

function dom_element_check(element){
    if (typeof element.nodeType !== 'undefined'){
        return true;
    }
    return false;
}
Zv_oDD
sumber
pertama-tama, Anda tidak perlu mengembalikan true atau return false, cukup kembalikan pernyataan if. Kedua, ini akan mengembalikan true untuk {nodeType: 1}
bluejayke
0

Metode benar mutlak, periksa target adalah kode primer elemen html nyata :

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

Tes di IE 5

dexiang
sumber
0

Setiap DOMElement.constructor mengembalikan fungsi HTML ... Element () atau [Object HTML ... Element] jadi ...

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ł
sumber
0

Saya punya cara khusus untuk melakukan ini yang belum disebutkan dalam jawaban.

Solusi saya didasarkan pada empat tes. Jika objek melewati keempatnya, maka itu adalah elemen:

  1. Objeknya bukan nol.

  2. Objek memiliki metode yang disebut "appendChild".

  3. Metode "appendChild" diwarisi dari kelas Node , dan bukan hanya metode peniru (properti yang dibuat pengguna dengan nama yang sama).

  4. Objeknya adalah Node Type 1 (Elemen). Objek yang mewarisi metode dari kelas Node selalu Nodes, tetapi tidak harus Elemen.

T: Bagaimana cara saya memeriksa apakah properti yang diberikan adalah warisan dan bukan hanya penipu?

A: Tes sederhana untuk melihat apakah suatu metode benar-benar diwarisi dari Node adalah untuk memverifikasi terlebih dahulu bahwa properti memiliki jenis "objek" atau "fungsi". Selanjutnya, konversi properti menjadi string dan periksa apakah hasilnya mengandung teks "[Kode Asli]". Jika hasilnya terlihat seperti ini:

function appendChild(){
[Native Code]
}

Maka metode ini telah diwarisi dari objek Node. Lihat https://davidwalsh.name/detect-native-function

Dan akhirnya, menyatukan semua tes, solusinya adalah:

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;
}
pengguna3163495
sumber
0
(element instanceof $ && element.get(0) instanceof Element) || element instanceof Element

Ini akan memeriksa bahkan jika itu adalah elemen jQuery atau JavaScript DOM

Arjun Kakkar
sumber
0

Satu-satunya cara untuk menjamin Anda memeriksa HTMLEement yang sebenarnya, dan bukan hanya objek dengan properti yang sama dengan Elemen HTML, adalah untuk menentukan apakah itu mewarisi dari Node, karena tidak mungkin untuk membuat Node () baru di JavaScript. (kecuali fungsi Node asli ditimpa, tetapi kemudian Anda kurang beruntung). Begitu:

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
sumber