JavaScriptオブジェクトがDOMオブジェクトであるかどうかをどのように確認しますか?


247

私は取得しようとしています:

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

私のスクリプトではtagName、プロパティとして必要になることはなかったので、これを使用していました。

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

したがって、2番目のオブジェクトについては、簡単な解決策として次のことを思いつきました。;)

問題は、読み取り専用プロパティを適用しているブラウザーに依存していることです。

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の一部です。

Update 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
これは、他のウィンドウ/フレームに属する要素では機能しないことに注意してください。アヒルのタイピングが推奨されるアプローチ
アンディE

2
あなたはそれをだますことができます:function Fake() {}; Fake.prototype=document.createElement("div"); alert(new Fake() instanceof HTMLElement);
Kernel James

11
WTFの事実:Firefoxの5およびそれ以前のリターンtrueのために[] instanceof HTMLElement
Rob W

6
ところで、HTMLElementは常になfunctionのでtypeof、トラックから外れ、ステートメントの2番目の部分が実行されます。instanceof Object関数はのインスタンスになるため、必要に応じて試すことができます。また、は両方ともネイティブオブジェクト関数であるため、をObject明示的にチェックするだけです。typeof === "function"NodeHTMLElement
Roland

2
を呼び出すとisElement(0)、falseではなく0が返されます。それはなぜですか。どうすればそれを防ぐことができますか?
ジェシカ

68

次のIE8互換の超シンプルなコードは完全に機能します。

受け入れ答えは、 HTML要素のすべてのタイプを検出しません。たとえば、SVG要素はサポートされていません。対照的に、この回答はHTMLとSVGの両方で機能します。

ここでそれを実際に見てください:https : //jsfiddle.net/eLuhbu6r/

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

3
IE7では「要素」は未定義
Dan

49
まだIE7を使用している人は、5秒かけてより良いブラウザをダウンロードするのではなく、時間を獲得するための拒否に取り組むために数日または数週間を費やす必要があると私は考えています。
mopsyd

1
私は@mopsydに同意しますが、回答の作成者はIE7で機能することを述べています。
Lajos Meszaros 2018

1
IE9と言うように更新されました。IE8でサポートされているかどうかは不明です。
モナークワディア

1
@MonarchWadiaはい、IE8でサポートされています。ただし、これはdocument(すべてのブラウザで)要素に対してtrueを返さないことに注意してください。あなたがそれを必要とする場合、あなたは試してみてください: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で「オブジェクト」を返します
Dennis 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;
}

11
これは機能しますか?それはまだ解決策です。クリエイティブなものです。
Justin Meyer、

3
これが提供する創造性と確実性のための+1。ただし、ノードが既にDOMの一部である場合は、削除しただけです。したがって、必要に応じてDOMに要素を再度追加する作業を行わないと、この回答は不完全になります。
svidgen 2013年

4
私はこれをほぼ5年後に読んでおり、それは最もクールなものの1つだと思います。洗練する必要があるだけです。たとえば、切り離された要素にノードのクローンを追加しようとすることができます。それがDOMオブジェクトでない場合。きっと何かがうまくいかないでしょう。しかし、それでもかなり高価なソリューションです。
MaxArt

またはその代わりに追加しようとしているのクローン要素のを、ちょうどそれのクローンを作成しようとすることは十分なはずです:obj.cloneNode(false)ANDには副作用はありません。
mauroc8 2017年

1
これは本当に高価であり、不必要に複雑です。以下の私の回答をご覧ください
。stackoverflow.com/ a /


6

どの程度LO-ダッシュの_.isElement

$ npm install lodash.iselement

そしてコードでは:

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

1
私はこのソリューションが好きです。これはシンプルで、EdgeとIEで機能します。ここで最も投票されたソリューションのほとんどとは異なり、個別のiframe内の要素でも機能します。
エリアスザマリア

この回答は役に立ちますが、ブラウザーでNPMモジュールを実行するにはWebpackが必要です。
エドウィンプラット

5

これは素敵なJavaScriptライブラリーMooToolsからです:

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

12
このコードは、オブジェクトがDOM要素であることを表明していません。それが少し似ているだけです。どのオブジェクトにもnodeNameおよびnodeTypeプロパティを指定でき、このコードを満たします。
thomasrutter

この回答では、すべてのタイプのHTML要素が検出されるわけではありません。たとえば、SVG要素はサポートされていません。以下の私の答えを参照してください。
モナークワディア2017

SVGなど、すべての要素に対して実際に機能するわけではありません。以下の私の回答をご覧ください
。stackoverflow.com/ a /

4

ここにあるルート検出を使用して、たとえばアラートがオブジェクトのルートのメンバーであるかどうかを判別できます。これは、ウィンドウである可能性が高いです。

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ソリューションよりも費用がかからないようです。

ドンP


私はこれを最新のChromeとFF、およびIE11でもテストしましたdocument.createElement()。また、DOMを介して作成されたが挿入されていないテキストノードやオブジェクトに対しても、どこでも機能します。すばらしい(:ありがとう
Geradlus_RU 2016年

これはまともな答えのように見えますが、私のものは多くの同じことを行い、それほど複雑ではありません。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
とても興味深い!場合によっては、objectsやpoperties にあるタイプに応じて、これは非常に便利です。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; },

//実際にはこれらをインラインで使用する可能性が高いですが、セットアップコードにこれらのショートカットを用意しておくとよい場合があります


IEでは関数にnameプロパティがないため、obj.constructor.nameはIEでは機能しません。obj.constructor!= Objectで置き換えます。
mathheadinclouds 2017年

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

上記のコードでは、二重否定演算子を使用して、引数として渡されたオブジェクトのブール値を取得しています。これにより、条件ステートメントで評価される各式がブール値であることを確認し、Short-Circuit Evaluationを利用して、関数リターンtrueまたはfalse


偽物はブール値を短絡させます。たとえばundefined && window.spam("should bork")、偽のspam関数を評価することはありません。!!必要ないので、信じていません。それは、その使用が重要な[非学術]エッジケースを提供できますか?
ルフィン、2015年

申し訳ありませんがありがとうございます。私が使用* !! *二重否定を truthyかfalsyない、ブール値をすべて表現を変換します。
jherax

そうです、しかしそれをする実際的な理由はないと思います、私は思いません- ここを見てください。また、ここではショートカット評価を利用する必要はありません。「!!必要ない」という引数を購入しなかったとしても(そして、購入しなかったのなら、なぜだろうと気になります)、その行を編集しreturn !!(obj && typeof obj === "object" && obj.nodeType === 1 && obj.nodeName);て同じように動作させることができます。
ruffin 2015年

それが私がやったことです;)よりクリーンで同じ効果。ありがとうございました。
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

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

ホット!この応答がゲームの勝者になるはずです。if(typeof obj.innerHTML!== 'string')// DOM要素ではありません。
user3751385 2014年

1
私は当初、以前の回答@Qtaxthomasrutterの批判に反応しましたが、私はそれを購入し始めています。私はこれまでまったく同じようにアヒルのようにしゃがむ犬に遭遇したことはありませんが、何かがノードであるかどうかを確認せずに実行しnotANode.innerHTML = "<b>Whoops</b>";、後でそのコードに汚染されたobjをこのコードに渡させることがわかります。防御的なコード===より良いコード、他のすべてのものは同等であり、これは最終的に防御的ではありません。
ruffin 2015年

2

Angularを使用している場合:

angular.isElement

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


Angularのコードを含めるとさらに便利: @finpingvinのコードにfunction isElement(node) { return !!(node && (node.nodeName || (node.prop && node.attr && node.find))); }少し似ています。それが決定されることに注意してください「の参照は、DOM要素(又は包まjQueryの要素)である場合。
ラフィン

2

プロトタイピングはあまり良い解決策ではないと思いますが、おそらくこれが最速の解決策です。このコードブロックを定義します。

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

次に、オブジェクトのisDomElementプロパティを確認します。

if(a.isDomElement){}

これがお役に立てば幸いです。


1
1)所有していないオブジェクトを変更することはお勧めできません。2)これは、同じドキュメントの一部ではない要素を検出しません。
fregante 2016年

2

mdnによると

ElementDocument継承内のすべてのオブジェクトの元になる最も一般的な基本クラスです。すべての種類の要素に共通のメソッドとプロパティしかありません。

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


1

私はあなたがしなければならないことは常にdom要素にあるいくつかのプロパティを徹底的にチェックすることだと思いますが、それらの組み合わせはおそらく次のように別のオブジェクトにはありません:

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

1

Firefoxでは、を使用できますinstanceof Node。それNodeDOM1で定義されています

しかし、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

2
良い試みですが、例外処理は回避できればコストがかかりすぎます。また、ES5では、オブジェクトの読み取り専用プロパティを定義できます。
アンディE

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

パフォーマンスを向上させるために、ブラウザーの機能を1回だけテストし、それに応じて適切な関数を割り当てる自己呼び出し関数を作成しました。

最初のテストはほとんどの最新のブラウザーで機能するはずであり、すでにここで説明されています。要素がインスタンスであるかどうかをテストするだけですHTMLElement。非常に簡単です。

2番目は最も興味深いものです。これがコア機能です。

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

elがそれがふりをしているconstrucorのインスタンスであるかどうかをテストします。そのためには、要素のコンストラクタにアクセスする必要があります。そのため、if-Statementでこれをテストしています。たとえばIE7はIE7にあるため、これ(document.createElement("a")).constructorは失敗しますundefined

このアプローチの問題は、document.createElement実際には最速の機能ではなく、多数の要素をテストしている場合、アプリケーションの速度が低下しやすいことです。これを解決するために、コンストラクターをキャッシュすることにしました。オブジェクトElementConstructorsは、対応するコンストラクターを値として持つnodeNamesをキーとして持ちます。コンストラクタがすでにキャッシュされている場合は、それをキャッシュから使用します。それ以外の場合は、Elementを作成し、将来のアクセスのためにコンストラクタをキャッシュしてから、それに対してテストします。

3番目のテストは、不快なフォールバックです。elがobjectnodeTypeプロパティがに設定され1、文字列がnodeNameます。もちろん、これはそれほど信頼できるものではありませんが、ユーザーの大多数はこれまでにフォールバックするべきではありません。

これは、可能な限り高いパフォーマンスを維持しながら、私が思いついた最も信頼できるアプローチです。



1

生のjsオブジェクトをHTMLElementと区別する

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

使用する:

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

// OR

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


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年です。「いいえ」と言ってください。
Thomas McCabe

0

これや他のものに手を出すのではなく、ES5準拠のブラウザの場合は、次の理由だけではありません。

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

などシャドウDOMやDocumentFragmentsわからTextNodesはなく上では動作しませんが、だろう、ほとんどすべてのHTMLタグ要素に取り組みます。


0

これは、ほとんどすべてのブラウザで機能します。(ここでは要素とノードの区別はありません)

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

まず第一に、trueやfalseを返す必要はなく、ifステートメントを返すだけです。次に、これは{nodeType:1}に対してtrueを返します
bluejayke

0

絶対正しい方法、チェックターゲットは実際の 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でテストする


0

DOMElement.constructorは、関数HTML ... Element()または[Object HTML ... Element] so ...を返します。

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

答えでまだ言及されていない、これを行う特別な方法があります。

私のソリューションは4つのテストに基づいています。オブジェクトが4つすべてを渡す場合、それは要素です。

  1. オブジェクトはnullではありません。

  2. オブジェクトには、「appendChild」というメソッドがあります。

  3. 「appendChild」メソッドはNodeクラスから継承されたもので、単なる偽のメソッド(ユーザーが作成した同じ名前のプロパティ)ではありません。

  4. オブジェクトはノードタイプ1(要素)です。Nodeクラスからメソッドを継承するオブジェクトは常にNodeですが、必ずしもElementではありません。

Q:特定のプロパティが継承されており、単なる詐称者ではないかどうかを確認するにはどうすればよいですか?

A:メソッドが本当にNodeから継承されたかどうかを確認する簡単なテストは、プロパティのタイプが「オブジェクト」または「関数」であることを最初に確認することです。次に、プロパティを文字列に変換し、結果に「[ネイティブコード]」というテキストが含まれているかどうかを確認します。結果が次のようになる場合:

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

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

これは、jQueryまたはJavaScript DOM要素であってもチェックします


0

HTML要素と同じプロパティを持つオブジェクトだけでなく、実際のHTMLEementをチェックしていることを保証する唯一の方法は、JavaScriptで新しいNode()を作成することが不可能であるため、Nodeから継承するかどうかを判断することです。(ネイティブの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--!>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.