我想要:
document.createElement('div') //=> true
{tagName: 'foobar something'} //=> false
在我自己的脚本中,我曾经只使用这个,因为我从来不需要tagName作为属性:
if (!object.tagName) throw ...;
所以对于第二个目标,我想出了下面的快速解决方案——这基本上是有效的。;)
问题是,它依赖于浏览器强制执行只读属性,而并非所有浏览器都这样做。
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;
}
}
有好的替代品吗?
我有一个特殊的方法来做到这一点,在答案中还没有提到。
我的解决方案基于四个测试。如果对象通过了这四个,那么它就是一个元素:
该对象不是空的。
对象有一个叫做“appendChild”的方法。
方法“appendChild”继承自Node类,而不仅仅是一个冒名方法(具有相同名称的用户创建的属性)。
对象类型为Node Type 1 (Element)。从Node类继承方法的对象总是Node,但不一定是element。
问:如何检查给定的属性是否是继承的,而不是冒名顶替的?
答:要判断一个方法是否真正继承自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;
}