286

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

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

良い代替品はありますか?

4

36 に答える 36

335

これは興味深いかもしれません:

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"
);
}
于 2008-12-21T12:10:59.220 に答える
91

次の IE8 互換の非常に単純なコードは完全に機能します。

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

ここで実際の動作を確認してください: https://jsfiddle.net/eLuhbu6r/

function isElement(element) {
    return element instanceof Element || element instanceof HTMLDocument;  
}
于 2016-04-27T15:53:25.460 に答える
27

ハックする必要はありません。要素が DOM Elementのインスタンスであるかどうかを尋ねるだけです。

const isDOM = el => el instanceof Element
于 2016-11-28T17:34:09.733 に答える
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それぞれを返す必要があります。メソッドをテストする唯一の方法は、メソッドが定義されているかどうかを確認することです。

于 2008-12-22T02:40:17.547 に答える
9

実際のDOMノードに追加してみることができます...

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

    return true;
}
于 2008-12-21T10:15:30.593 に答える
7

ローダッシュは_.isElementどうですか?

$ npm install lodash.iselement

そしてコードで:

var isElement = require("lodash.iselement");
isElement(document.body);
于 2014-11-24T19:07:22.507 に答える
7

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

if (obj.nodeName){
    switch (obj.nodeType){
    case 1: return 'element';
    case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
    }
}
于 2008-12-21T09:52:12.200 に答える
4

古いスレッドですが、ie8 および ff3.5ユーザー向けの更新された可能性があります:

function isHTMLElement(o) {
    return (o.constructor.toString().search(/\object HTML.+Element/) > -1);
}
于 2011-03-02T19:00:48.823 に答える
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 ソリューションよりもコストがかからないようです。

ドン・P

于 2013-12-09T17:14:47.980 に答える
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

于 2014-10-21T22:28:48.073 に答える
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; },

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

于 2013-12-22T00:26:12.307 に答える
3

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

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

オブジェクトの isDomElement プロパティを確認するよりも:

if(a.isDomElement){}

これが役立つことを願っています。

于 2015-11-04T10:43:58.283 に答える
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
于 2012-08-23T16:43:59.727 に答える
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

于 2018-12-27T14:22:13.630 に答える
1

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

しかし、IEではそれはそれほど簡単ではありません。

  1. 「instanceofActiveXObject」は、それがネイティブオブジェクトであることのみを認識できます。
  2. "typeof document.body.appendChild =='object'"は、それがDOMオブジェクトである可能性があることを示していますが、同じ機能を持つ他のオブジェクトである可能性もあります。

DOM関数を使用してDOM要素であることを確認し、例外がある場合にのみキャッチできます。ただし、副作用が発生する可能性があります(オブジェクトの内部状態/パフォーマンス/メモリリークの変更など)

于 2008-12-21T15:50:19.373 に答える
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 がコンストラクターのインスタンスであるかどうかをテストします。そのためには、要素のコンストラクターにアクセスする必要があります。そのため、if ステートメントでこれをテストしています。たとえばIE7はIE7にあるため、これに失敗し(document.createElement("a")).constructorますundefined

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

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

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

于 2013-02-07T00:38:29.567 に答える
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
于 2012-01-05T00:34:40.787 に答える
1

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

var isDom = function (inp) {
    return inp && inp.tagName && inp.nodeName && inp.ownerDocument && inp.removeAttribute;
};
于 2008-12-21T09:53:10.763 に答える
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

于 2015-12-28T12:41:51.957 に答える
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 でテスト

于 2016-05-06T19:56:46.130 に答える
0

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

私の解決策は、4 つのテストに基づいています。オブジェクトが 4 つすべてに合格した場合、それは要素です。

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

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

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

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

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

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;
}
于 2016-10-15T18:15:28.177 に答える
0
(element instanceof $ && element.get(0) instanceof Element) || element instanceof Element

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

于 2017-02-10T10:46:16.090 に答える
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));

}
于 2013-11-09T14:41:08.573 に答える
-1

ほとんどの回答では、オブジェクトにプロパティがあることを確認するなど、ある種のダックタイピングを使用していnodeTypeます。しかし、それだけでは十分ではありません。非ノードもノードのようなプロパティを持つことができるからです。

もう 1 つの一般的なアプローチは です。これは、ノード プロパティを継承しているにもかかわらず、ノードではない などでinstanceof誤検知を引き起こす可能性があります。Object.create(Node)

さらに、上記の両方のアプローチは、たとえばテストされた値がプロキシである場合に問題になる可能性がある内部の必須メソッドを呼び出します。

代わりに、ノード メソッドを借用してオブジェクトで呼び出すことをお勧めします。ブラウザは、おそらくプロキシでカスタマイズできない内部スロットを見て、値がノードであることを確認します。

function isNode(value) {
  try {
    Node.prototype.cloneNode.call(value, false);
    return true;
  } catch(err) {
    return false;
  }
}

必要に応じて、プロパティ ゲッターを使用することもできます。

function isNode(value) {
  try {
    Object.getOwnPropertyDescriptor(Node.prototype,'nodeType').get.call(value);
    return true;
  } catch(err) {
    return false;
  }
}

同様に、値が要素かどうかをテストする場合は、次を使用できます

function isElement(value) {
  try {
    Element.prototype.getAttribute.call(value, '');
    return true;
  } catch(err) {
    return false;
  }
}
function isHTMLElement(value) {
  try {
    HTMLElement.prototype.click.call(value);
    return true;
  } catch(err) {
    return false;
  }
}
于 2016-08-28T22:16:27.183 に答える
-1
var isElement = function(e){
    try{
        // if e is an element attached to the DOM, we trace its lineage and use native functions to confirm its pedigree
        var a = [e], t, s, l = 0, h = document.getElementsByTagName('HEAD')[0], ht = document.getElementsByTagName('HTML')[0];
        while(l!=document.body&&l!=h&&l.parentNode) l = a[a.push(l.parentNode)-1];
        t = a[a.length-1];
        s = document.createElement('SCRIPT');   // safe to place anywhere and it won't show up
        while(a.length>1){  // assume the top node is an element for now...
            var p = a.pop(),n = a[a.length-1];
            p.insertBefore(s,n);
        }
        if(s.parentNode)s.parentNode.removeChild(s);
        if(t!=document.body&&t!=h&&t!=ht)
            // the top node is not attached to the document, so we don't have to worry about it resetting any dynamic media
            // test the top node
            document.createElement('DIV').appendChild(t).parentNode.removeChild(t);
        return e;
    }
    catch(e){}
    return null;
}

これを Firefox、Safari、Chrome、Opera、IE9 でテストしました。ハッキングする方法が見つかりませんでした。
理論的には、提案された要素のすべての祖先と要素自体を、その前にスクリプト タグを挿入してテストします。その最初の祖先が 、 、など
の既知の要素にさかのぼり、途中でエラーをスローしなかった場合、要素が存在します。 最初の祖先がドキュメントに添付されていない場合、要素を作成し、提案された要素をその中に配置しようとします (その後、新しい要素から削除します)。 したがって、既知の要素にトレースバックするか、既知の要素に正常に接続するか、失敗します。 要素を返すか、要素でない場合は null を返します。<html><head><body>


于 2012-03-29T10:47:10.757 に答える
-1

要素が HTML DOM の一部であるかどうかを検出する最も簡単なクロスブラウザーの方法は次のとおりです。

function inHTMLDom(myelement){
    if(myelement.ownerDocument.documentElement.tagName.toLowerCase()=="html"){
        return true;
    }else{
        return false;
    }
}

inHTMLDom(<your element>); // <your element>:element you are interested in checking.

IE6、IE7、IE8、IE9、IE10、FF、Chrome、Safari、Operaでテスト済み。

于 2013-08-15T06:54:09.900 に答える
-1

私はこの機能を使用します:

function isHTMLDOMElement(obj) {
  if (Object.prototype.toString.call(obj).slice(-8) === 'Element]') {
    if (Object.prototype.toString.call(obj).slice(0, 12) === '[object HTML') {
      return true;
    }
    return false;
  }
  return false;
}

https://jsfiddle.net/1qazxsw2/wz7e0fvj/9/

于 2021-04-07T11:00:53.263 に答える