2014-10-24 2 views
4

Я просто просматривал несколько фотографий с конференции нг-Европа в этом году, и заметил, что слайд я думаю, мог бы показать код от предстоящего угловыми 2. Смотрите здесь:Зачем использовать Array.prototype.forEach.call (array, cb) для array.forEach (cb)?

Example from ng-europe

(Источник: https://plus.google.com/u/0/photos/+ThierryLAU/albums/6073085583895256529/6073092865671487010?pid=6073092865671487010&oid=105910465983441810901)

То, что я не получаю это:

Почему автор этого кода с использованием Array.prototype.forEach.call(array, cb) в предпочтении тех короче и (по-моему) эквивалентной версия array.forEach(cb). Единственная причина, по которой я мог себе представить, - это последствия для производительности.

Кто-нибудь знает о другой разнице? Или, может быть, я прав, когда думаю, что у меня получается?

+0

Возможный дубликат [JS - Зачем использовать Prototype?] (Http://stackoverflow.com/questions/8433459/js-why-use-prototype) –

+0

Основная причина, по которой '[] .forEach.call (arr) 'используется для предотвращения объектов типа массива (объект' arguments', списки узлов DOM и т. д.), вызывая ошибку, поскольку 'Array.prototype' не находится в цепочке прототипов этих объектов. Вот очень похожий вопрос, но спросил с другой стороны: http://stackoverflow.com/questions/1424710/why-is-my-join-on-a-javascript-array-failing –

+0

@ Qantas. Спасибо за ответ. Но почему вы оставили его в качестве комментария вместо ответа? – NicBright

ответ

7

Есть номер Array-like objects, которые выглядят как массивы, однако их нет. Для того, чтобы назвать несколько:

  • arguments
  • children и childNodes коллекции
  • Nodelist коллекции возвращаемые методами, как document.getElementsByClassName и document.querySelectorAll
  • коллекции JQuery
  • и даже строки.

Многие методы массива прототипа являются универсальными по назначению, а это значит, что их внутренняя реализация не зависит от контекста this быть экземпляром Array конструктора. Это позволяет вызывать эти методы в контексте других объектов, которые «выглядят» как массивы. А именно, похожий на массив означает, что объект имеет числовые ключи и свойство length.

Вот один бесполезный пример того, как можно вызвать Array.prototype.join на пользовательский массив типа объекта:

Array.prototype.join.call({0: 'one', 1: 'two', length: 2}, ' '); 

Выше строки вывода "one two" воли. Однако поставляемый объект явно не является массивом.

+0

, но почему он все еще работает, если мы передаем 'this'' window'? Это объект типа Array? Например: 'Array.prototype.forEach.call (window, function (element, index, array) {console.log (index, element, array)})' – Sotiris

+1

@Sotiris Обычно то, что вы разместили, не будет работать на * any * стр. Я предполагаю, что, поскольку это сработало для вас, вы протестировали этот скрипт на странице с фреймами, я прав?Еще один раз: быть массивным объектным объектом должен иметь свойство length и числовые ключи: 0, 1 и т. Д. Если в документе есть кадры, тогда 'window.length' показывает, сколько из них и окна [0], окна [ 1] и т. Д. Ссылаются на эти фреймы/фреймы, чтобы они отображались в документе. Таким образом, в этом случае объект 'window' действительно становится подобным массиву, поскольку он позволяет получить доступ к некоторым свойствам с помощью числовых индексов, а также имеет свойство length. – dfsq

+0

Большое спасибо за понимание. Действительно, это были фреймы некоторых плагинов. Тестирование на инкогнито возвращает неопределенное, как ожидалось. – Sotiris

1

Это бит защиты от element.attributes или element.children не является массивом.

Смежные вопросы