lodash's isElement 等价于纯 JS



现在我使用isElement通过lodash来检查元素是否可能是DOM。我想摆脱这个库,所以我正在寻找这个函数的纯JS实现。

我正在使用这个,但我不知道它的实现是否正确,以及我是否忽略了任何边缘情况:

const isDOMElement = el => el instanceof HTMLElement

更新

我已经测试了四种建议的实现(codepen链接),在所有情况下都如预期的那样工作,也许@cesare提出的方案涵盖了大多数情况,但@peter-seliger提出的方案也很聪明,并且使用了"outside of the box";思考。最后,@David Thomas和我第一次使用的那个,在大多数情况下都有效。

总之,我认为,正如David Thomas指出的It's just a matter of preference

p。S:用于测试的标签是从MDN的HTML元素引用

中提取的。p。S2:我不知道该怎么做,也不知道该接受什么样的回答。cesare和peter都有一个很好的观点

可以试着…

function exposeImplementation(value) {
return Object
.prototype
.toString
.call(value);
}
function getInternalClassName(value) {
return (/^[objects+(?<className>[^]]+)]$/)
.exec(
exposeImplementation(value)
)
?.groups
?.className;
}
function isHTMLElement(value) {
return !!value && (/^HTML(?:[A-Z][A-Za-z]+)?Element$/)
.test(
String(
getInternalClassName(value)
)
);
}
console.log(
getInternalClassName(document.createElement('h1')),
isHTMLElement(document.createElement('h1'))
);
console.log(
getInternalClassName(document.body),
isHTMLElement(document.body)
);
console.log(
getInternalClassName(document),
isHTMLElement(document)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

这是lodashutil:

function isElement(value) {
return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value)
}

基本上与isObjectLike它检查传递的值是非null对象(因为null是js中的对象)和!isPlainObject,它不是一个普通对象(因为它可能是一个对象携带"nodeType": 1条目,因为一个HTMLElement实例有嵌套protos。

isPlainObjectutil是这样的:

function isPlainObject(value) {
if (!isObjectLike(value) || getTag(value) != '[object Object]') {
return false
}
if (Object.getPrototypeOf(value) === null) {
return true
}
let proto = value
while (Object.getPrototypeOf(proto) !== null) {
proto = Object.getPrototypeOf(proto)
}
return Object.getPrototypeOf(value) === proto
}

正如你所看到的,第一个检查是多余的,因为它再次检查了isObjectLike,但在我看来,主要的警告是它不包括其他对象的情况,因为例如" array& quot;也是对象,因此它们通过了检查:

const arr = [1, 2]; // array
arr.nodeType = 1; // add nodeType property to the array object
console.log(isElement(arr)); // true Lodash

你自己试试。

我认为检查对象是否有继承的nodeType属性更安全:

const _isElement = (node) =>
typeof node === 'object' &&
node !== null &&
!node.hasOwnProperty('nodeType') &&
node.nodeType &&
node.nodeType === 1

const el = document.createElement('h1'); // node
const arr = [1, 2]; // array
arr.nodeType = 1; // add nodeType property to the array object
console.log(isElement(arr)); // true Lodash
console.log(isElement(el)); // true Lodash
console.log(_isElement(arr)) // false
console.log(_isElement(el)) // true

在任何情况下,我更喜欢使用你的检查已经涵盖了大部分的检查,因为任何原始的非对象不是HTMLElement的实例,null不是HTMLElement的实例,并且HTMLElement实例有一个"nodeType"属性,但它是从原型继承而不是一个自己的属性,:

const isDOMElement = el => el instanceof HTMLElement
//or
const isDOMElement = el => el instanceof Node

查看库源代码的实现:

https://github.com/lodash/lodash/blob/master/isElement.js

相关内容

  • 没有找到相关文章

最新更新