私は取得しようとしています:
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;
}
}
良い代用品はありますか?
これは興味深いかもしれません:
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"
);
}
次のIE8互換の超シンプルなコードは完全に機能します。
受け入れられた回答 は、すべてのタイプのHTML要素を検出しません。たとえば、SVG要素はサポートされていません。対照的に、この答えはHTMLでもSVGでも機能します。
こちらで実際にご覧ください: https://jsfiddle.net/eLuhbu6r/
function isElement(element) {
return element instanceof Element || element instanceof HTMLDocument;
}
上下のすべてのソリューション(私のソリューションを含む)は、特に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ノードに適したテストです。ただし、安全を確保したい場合は、常にメソッドとプロパティの存在を確認し、それらのタイプを確認してください。
EDIT: IEは、ノードを表すためにActiveXオブジェクトを使用するため、それらのプロパティは真のJavaScriptオブジェクトとして動作しません。例:
console.log(typeof node.cloneNode); // object
console.log(node.cloneNode instanceof Function); // false
一方、それぞれ「関数」とtrue
を返す必要があります。メソッドをテストする唯一の方法は、定義されているかどうかを確認することです。
実際のDOMノードに追加してみてください...
function isDom(obj)
{
var Elm = document.createElement('div');
try
{
Elm.appendChild(obj);
}
catch (e)
{
return false;
}
return true;
}
Lo-Dashの_.isElement
はどうですか?
$ npm install lodash.iselement
そしてコードでは:
var isElement = require("lodash.iselement");
isElement(document.body);
これは、素敵なJavaScriptライブラリからのものです MooTools :
if (obj.nodeName){
switch (obj.nodeType){
case 1: return 'element';
case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
}
}
古いスレッドですが、ここではie8およびff3.5ユーザーの更新された可能性があります。
function isHTMLElement(o) {
return (o.constructor.toString().search(/\object HTML.+Element/) > -1);
}
ルート検出を使用して here が見つかりました。 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
これは役に立つかもしれません: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);
}
上記のコードでは、double negation演算子を使用して、引数として渡されたオブジェクトのブール値を取得します。これにより、各式が条件文はブール値で、Short-Circuit Evaluationを利用するため、関数はtrue
またはfalse
を返します。
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; },
//実際、私はこれらのインラインを使用する可能性は低いですが、セットアップコードにこれらのショートカットを使用するのが良い場合もあります
変数がDOM要素かどうかをテストする簡単な方法を提案します
function isDomEntity(entity) {
if( typeof entity === 'object' && entity.nodeType != undefined){
return true;
}
else{
return false;
}
}
ハックの必要はありません。要素が Element のインスタンスであるかどうかを尋ねることができます。
const isElement = el => el instanceof Element
問題のオブジェクトまたはノードが文字列型を返すかどうかを確認できます。
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
生の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
Firefoxでは、instanceof Node
を使用できます。 Node
は DOM1 で定義されています。
しかし、それはIEではそれほど簡単ではありません。
DOM関数を使用して例外をキャッチすることによってのみ、DOM要素であることを確認できます。ただし、副作用がある可能性があります(たとえば、オブジェクトの内部状態/パフォーマンス/メモリリークの変更)
これは私が理解したものです:
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-Statementでこれをテストしている理由です。たとえばIE7では、(document.createElement("a")).constructor
がIE7ではundefined
であるため、これは失敗します。
このアプローチの問題は、document.createElement
が実際には最速の関数ではなく、多くの要素をテストしている場合、アプリケーションの速度が低下する可能性があることです。これを解決するために、コンストラクターをキャッシュすることにしました。オブジェクトElementConstructors
には、対応するコンストラクターを値として持つキーとしてのnodeNameがあります。コンストラクターがすでにキャッシュされている場合は、キャッシュからコンストラクターを使用します。そうでない場合は、エレメントを作成し、将来のアクセスのためにコンストラクターをキャッシュしてからテストします。
3番目のテストは、不快なフォールバックです。 elがobject
であるか、nodeType
プロパティが1
に設定され、文字列がnodeName
であるかどうかをテストします。もちろん、これはそれほど信頼できるものではありませんが、大多数のユーザーはこれまでのところフォールバックするべきではありません。
これは、可能な限り高いパフォーマンスを維持しながら、私が思いついた最も信頼できるアプローチです。
おそらくこれは代替手段ですか? 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
プロトタイピングはあまり良い解決策ではないと思いますが、これが最速の解決策かもしれません。このコードブロックを定義してください。
Element.prototype.isDomElement = true;
HTMLElement.prototype.isDomElement = true;
オブジェクトのisDomElementプロパティを確認するよりも:
if(a.isDomElement){}
これがお役に立てば幸いです。
これは、ほとんどすべてのブラウザーで機能します。 (ここでは要素とノードの区別はありません)
function dom_element_check(element){
if (typeof element.nodeType !== 'undefined'){
return true;
}
return false;
}
あなたがしなければならないことは、常にdom要素にあるいくつかのプロパティを徹底的にチェックすることだと思いますが、それらの組み合わせはほとんどの場合別のオブジェクトにはありません:
var isDom = function (inp) {
return inp && inp.tagName && inp.nodeName && inp.ownerDocument && inp.removeAttribute;
};
ES5に準拠したブラウザの場合、これだけではありません。
function isDOM(e) {
return (/HTML(?:.*)Element/).test(Object.prototype.toString.call(e).slice(8, -1));
}
TextNodeでは機能せず、Shadow DOMやDocumentFragmentsなどについてはわかりませんが、ほとんどすべてのHTMLタグ要素でwillが機能します。
各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;
}
ここに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));
}
私はこれを行うための特別な方法を持っていますが、答えにはまだ言及されていません。
私のソリューションは4つのテストに基づいています。オブジェクトが4つすべてを通過する場合、それは要素です。
オブジェクトはヌルではありません。
オブジェクトには、「appendChild」というメソッドがあります。
メソッド「appendChild」はNodeクラスから継承されたもので、単なる偽者メソッドではありません(同じ名前のユーザー作成プロパティ)。
オブジェクトはNode Type 1(Element)です。 Nodeクラスからメソッドを継承するオブジェクトは常にノードですが、必ずしも要素ではありません。
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;
}
絶対的な正しい方法であるチェック対象は、realhtml要素のプライマリコードです:
(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);
(element instanceof $ && element.get(0) instanceof Element) || element instanceof Element
これは、jQueryまたはJavaScript DOM要素であってもチェックします
mdn による
Element
は、Document
内のすべてのオブジェクトが継承する最も一般的な基本クラスです。すべての種類の要素に共通のメソッドとプロパティのみがあります。
プロトタイプでisElement
を実装できます。私のアドバイスは次のとおりです。
/**
* @description detect if obj is an element
* @param {*} obj
* @returns {Boolean}
* @example
* see below
*/
function isElement(obj) {
if (typeof obj !== 'object') {
return false
}
let prototypeStr, prototype
do {
prototype = Object.getPrototypeOf(obj)
// to work in iframe
prototypeStr = Object.prototype.toString.call(prototype)
// '[object Document]' is used to detect document
if (
prototypeStr === '[object Element]' ||
prototypeStr === '[object Document]'
) {
return true
}
obj = prototype
// null is the terminal of object
} while (prototype !== null)
return false
}
console.log(isElement(document)) // true
console.log(isElement(document.documentElement)) // true
console.log(isElement(document.body)) // true
console.log(isElement(document.getElementsByTagName('svg')[0])) // true or false, decided by whether there is svg element
console.log(isElement(document.getElementsByTagName('svg'))) // false
console.log(isElement(document.createDocumentFragment())) // false