Я правильно понял этот код Function.prototype.call()?

Код:

var content = Array.prototype.map.call(document.getElementsByTagName("p"), function(e) {
  return e.innerHTML;
}); 

Это из п. 367 JavaScript: окончательное руководство, 6-е изд.

Здесь я думаю, что это происходит в этом коде.

Переменной content присваивается результат вызова .map() в теге NodeList тегов абзаца, возвращаемых document.getElementsByTagName("p").

Доступ к методу .map() осуществляется из Array.prototype, а его значение this установлено как тег абзаца NodeList, используя .call(). Поскольку .map() применяет функцию, имеющую доступ к item, index, array, e in function(e) является элементом NodeList.

Таким образом, переменная content заканчивается состоянием результата .innerHTML вызывает каждый из Element тип Nodes в NodeList, состоящий из тегов абзаца в текущем документе.

.innerHTML вернет текст данного элемента HTML, если в нем нет других узлов. В противном случае он вернет HTML-узлы внутри него.

Это правильно? Я пробовал:

  • Чтение Документация MDN по функции .prototype.call
  • Поиск программистов SE Я нашел Неверное понимание, которое я не уверен, как интерпретировать. Он утверждает, что документация MDN неполна.
  • Чтение больше в книге окончательных версий.
  • Беседа в JSFiddle - код действует так, как ожидалось, я просто хочу знать, как он делает то, что он делает.

Ответ 1

Да, это именно то, что происходит.

Просто быть очень разборчивым:

.innerHTML вернет текст данного элемента HTML, если в нем нет других узлов. В противном случае он вернет HTML-узлы внутри него.

.innerHTML всегда возвращает содержимое HTML элемента, независимо от того, содержит ли он детей или нет. Просто трудно определить разницу между текстом элемента и HTML элемента, когда он не содержит детей (но есть разница!).

HTML:

<div>&lt;</div>

JS:

console.log(document.getElementsByTagName("div")[0].innerHTML); // "&lt;"
console.log(document.getElementsByTagName("div")[0].textContent); // "<"

FWIW, это возможно в первую очередь потому, что многие методы JavaScript предпочитают утиную печать, полагаясь на наследование

Когда я вижу птицу, которая ходит как утка и плавает, как утка и шарлатанья, как утка, я называю эту птицу уткой

Из-за этого map() с радостью предоставит вам map() любой объект, который будет похож на массив (т.е. имеет свойство .length).

Вы также могли бы использовать:

var content = [].map.call(document.getElementsByTagName("p"), function(e) { return e.innerHTML; }); 

... но первый предпочтительнее, потому что вам не нужно создавать, а затем выбросить массив, чтобы получить доступ к функции map().