Я пытаюсь реализовать собственный document.getElementById в javascript. Я реализовал document.getElementsByClassName в javascript.
function getElementsByClassName (className) {
var nodeList = [];
function test(node) {
if (node.classList && node.classList.contains(className)) {
nodeList.push(node);
}
for (var index = 0; index < node.childNodes.length; index++) {
test(node.childNodes[index]);
}
return nodeList;
}
test(document.body);
return nodeList;
};
// Fails here.
function getElementById(className) {
const result = [];
function getEachIDNode(node) {
if (node.contains(className)) {
return node;
}
for(let i=0; i<node.childNodes.length; i++) {
getEachIDNode(node.childNodes[i]);
}
}
getEachIDNode(document.body);
}
console.info(getElementsByClassName('winner'));
console.info(getElementById('test')); <table>
<tr id = "test">
<td>#</td>
<td class = "winner">aa</td>
<td>bb</td>
<td>cc</td>
<td>dd</td>
</tr>
</table>
<table>
<tr>
<td>#</td>
<td class = "winner">aa</td>
<td>bb</td>
<td>cc</td>
<td>dd</td>
</tr>
</table>
<table>
<tr>
<td>#</td>
<td class = "winner">dd</td>
<td>cc</td>
<td>bb</td>
<td>aa</td>
</tr>
</table>Я пытаюсь понять, как я могу проверить, есть ли у узла идентификатор атрибута.
Может кто меня просветить?
Вы можете напрямую проверить node.id === className. Хотя, className - странное название аргумента для getElementById.
@VicJordan готово. пожалуйста, проверьте. я добавил свою реализацию.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Сравните свойство id узла с переданным аргументом (возможно, лучше использовать id в качестве аргумента, а не className):
function getElementById(id) {
const result = [];
function getEachIDNode(node) {
if (node.id === id) {
result.push(node);
}
for(let i=0; i<node.childNodes.length; i++) {
getEachIDNode(node.childNodes[i]);
}
}
getEachIDNode(document.body);
return result;
}
console.info(getElementById('subchild')[0].innerHTML);<div id = "parent">
<div id = "child1">
</div>
<div id = "child2">
<div id = "subchild">
subchild!
</div>
</div>
</div>Но если вы фактически хотите реплицировать getElementById, не пытайтесь вернуть массив, верните один элемент
:
function getElementById(id) {
let match = null;
const doFind = node => {
if (!match && node.id === id) match = node;
if (!match) return [...node.childNodes].find(doFind);
}
doFind(document.body);
return match;
}
console.info(getElementById('subchild').innerHTML);<div id = "parent">
<div id = "child1">
</div>
<div id = "child2">
<div id = "subchild">
subchild!
</div>
</div>
</div>Любопытный вопрос: зачем нам нужен массив результатов, если мы знаем, что идентификатор уникален? не можем ли мы вернуться напрямую из оператора if?
Да, было бы лучше вернуть один элемент, если вы действительно хотите воспроизвести getElementById. Массив здесь не имеет особого смысла (была ли причина, по которой вы пытались его использовать?)
Ах, не совсем так. Позже я повторно просматривал свой код, и тогда у меня возникла эта мысль! Спасибо за Ваш ответ.
@TechnoCorner, пожалуйста, не забудьте принять и проголосовать за ответ, если вы сочтете его полезным.
Проверить свойство атрибута элемента DOM.
function getElementById(id) {
const result = [];
function getEachIDNode(node) {
if (!(node instanceof HTMLElement))
return;
if (node.hasAttribute('id') && node.getAttribute('id') === id) {
result.push(node);
}
for(let i=0; i<node.childNodes.length; i++) {
if (result.length > 0)
return;
getEachIDNode(node.childNodes[i]);
}
}
getEachIDNode(document.body);
return result[0];
}
Значит, элементы <svg> и их дочерние элементы исключены?
Никакие <svg> не выполняются, поскольку <svg> не являются instanceof HTMLElement.
Собственный document.getElementById не просматривает дерево DOM в поисках вашего Элемента, и поэтому он быстрее, чем другие методы выбора DOM.
Действительно, браузеры должны хранить своего рода хеш-карту всех элементов с идентификатором в активном документе. Таким образом, они просто просматривают этот хеш-карта (который не является одним из них) и возвращают элемент, если они его нашли.
Благодаря IE </irony> они действительно предоставляют некоторые записи этого хеш-карта как свойства глобального объекта window.
Поэтому, если вы собираетесь создать свою собственную реализацию, вы можете сначала проверить, возвращает ли это свойство ваш Element.
К сожалению, может случиться так, что идентификатор элемента действительно совпадает с другим свойством объекта window. Так что может случиться так, что мы все же нужно пройти DOM.
В этом случае используйте TreeWalker, который представляет собой самый быстрый API, который мы должны пройти по дереву DOM, более того, когда нас интересуют только некоторые типы узлов (здесь элементы).
В общем, лучшая реализация могла бы выглядеть так:
function getElementById(id) {
if (!(id in window)) {
console.info(id, 'not found');
return null; // we are sure it's not set
}
// id maps are not marked as 'own property'
if (!window.hasOwnProperty(id)) {
if (window[id] instanceof Element &&
window[id].id === id) { // it's our Element
console.info(id, 'found in window');
return window[id];
}
// in case of duplicate window[id] should return an HTMLCollection
// (IIRC only Chrome does it correctly though)
if (window[id] instanceof HTMLCollection &&
window[id][0].id === id) {
console.info(id, 'duplicate id is bad');
return window[id][0];
}
}
console.info(id, 'walking...');
var walker = document.createTreeWalker(
document.documentElement,
NodeFilter.SHOW_ELEMENT,
null,
false
);
while (walker.nextNode()) {
if (walker.currentNode.id === id) {
return walker.currentNode;
}
}
return null;
}
console.info(getElementById('foo'));
console.info(getElementById('unique'));
console.info(getElementById('duplicate'));
window.overwritten = 'oups';
console.info(getElementById('overwritten'));<div id = "unique">
<div id = "duplicate"></div>
<div id = "duplicate"></div>
<div id = "overwritten"></div>
</div>Как видите, в этой реализации мы просматриваем DOM только в том случае, если для свойства окна установлено другое значение, что значительно улучшает производительность.
Чтобы проверить, есть ли у узла идентификатор атрибута, вы должны написать вот так:
var attr_check = $(".selector").attr('id')
if (attr_check != undefined || attr_check != false)
{
console.info("this element has attribute id")
}
Вы также пишете этот код:
var attr_check = document.getElementById('div-id').attr('id')
вместо этого:
var attr_check = $(".selector").attr('id')
также добавьте свой html-код, а также, если возможно, предоставьте исполняемый код