Структура объекта NodeList JS

132
30 мая 2019, 18:30

Здравствуйте, интересует как устроен объект NodeList и ему подобные.

  1. Почему он NodeList отображается как массив childNodes: NodeList[9], а не так childNodes: NodeList и как это сделали?
  2. elem.childNodes.length сработает геттер на этом свойстве и возможно пересчитает содержимое, но почему оно дублируется в самом объекте и прототипе?
  3. И самое понятное для меня, учитывая особенности выше, почему имя прототипа такое же, как и у объекта, он наследует сам себя? Для чего так сделано и как?

Как структурно создать такой же объект? Если это возможно.

Answer 1

NodeList - как уже говорилось ранее, это интерфейс, реализация которого скрыта в недрах браузера. Поэтому что именно делает свойство length и как оно работает именно для этой коллекции: перессчитывает при каждом обращении либо где-то кэширует значение, можно узнать лишь погрузившись в исходники конкретного браузера.

Что касается отображения просматриваемых объектов в консоли.

То, как именно показывает консоль, по большей части никак не регламентировано. Поэтому в разных браузерах вывод будет выглядеть по разному.

Если рассматривать конкретно Chrome.

Имя выводимое напротив proto можно определить использовав свойство с именем Symbol.toStringTag

Кроме того, данное свойство влияет на работу Object.prototype.toString

Теперь самое интересное: для вывода как массива, консоль должна подумать, что выводит массив.

Самый простой путь: унаследоваться от класса Array

class MyArr extends Array{
}

Но можно обойтись и обычными объектами.

Непонятно чем руководствовались разработчики, но при наличии в объекте свойства splice, со значением в виде функции, а так же свойства length, консоль Chrome начинает отображать данный объект как массив:

var base = {
    get length(){return 0;}
    splice(){}
}

Будет выглять в консоли так:

и в развернутом виде:

Теперь все готово, чтобы сделать объект очень похожий в выводе на NodeList

function NL() { 
  this.splice = function() {}; 
} 
 
NL.prototype = { 
  length: 0, // значение свойства по умолчанию 
  push(el) { 
    this[this.length] = el; 
    this.length++; 
  }, 
  [Symbol.toStringTag]: "NL" 
}; 
 
 
var nl = new NL(); 
nl.push(10); 
nl.push(20); 
console.debug({ 
  a: nl 
}); 
console.log(nl + ''); 
console.log(Object.prototype.toString.call(nl));

При выполнении сниппета в консоли Chrome можно увидеть следующее:

Что весьма похоже на картинку в вопросе.

Answer 2
  1. Это массивоподобный объект. Т. е. объект, ключи которого порядковые числа и есть свойство length. Эти объект почти всамделишные массивы, поэтому и есть общие черты. Кстати, вид подсказки зависит от браузера. Кто-то любезно подскажет длину, кто-то в скобках выведет сами узлы (FF), а кто-то выведет Object, кто будет верно, хотя и грубо :)
  2. Геттер необходим из-за того, что это, на самом деле, "живая" коллекция. Т. е. изменения в DOM, относительно узла, и происходит пересчёт.
    Правда это скорее догадка, буду рад, если знающий добавит суровых правил.
  3. Имя, как уже говорилось, может быть любым, зависит от браузера. Но логично что объект можно назвать в честь конструктора.

На счёт создания похожего объект я не понял. Создаёте конструктор, объект от него и вуаля.
Правда имя для пользовательского объекта подставит только хром, лиса презрительно назовёт объект как Object { ... }.

P. S. Конечно, не стоит игнорировать истину в предпоследней инстанции. Последняя инстанция тут.
Спасибо @Grundy за ссылки, без него пришлось бы гуглить :)

READ ALSO
YouTube подписаться на канал через консоль

YouTube подписаться на канал через консоль

Я не очень разбираюсь в работе js и пр, но мне нужен кое-какой функционал и я хотел бы спросить об этом у людей, которые понимают в этом

135
Плавающее меню, javascript на сайте

Плавающее меню, javascript на сайте

Такая проблема, вот на этом сайте http://mnogobuketovru/test

148
React не получается найти данные в объекте [закрыт]

React не получается найти данные в объекте [закрыт]

Есть код который передает массив в другой компонент, далее мне просто нужно найти в нем свойство thumb

163
Отличия свойства от переменной

Отличия свойства от переменной

В чем отличие свойства объекта от переменной глобального объекта?

125