Я нашел следующую аннотацию цикла в большом проекте, над которым я работаю (псевдокод):
var someOtherArray = [];
for (var i = 0, n = array.length; i < n; i++) {
someOtherArray[i] = modifyObjetFromArray(array[i]);
}
Что привлекло мое внимание, так это дополнительная «n» переменная. Я никогда раньше не видел написанного таким образом.
Очевидно, что в этом сценарии нет причин, по которым этот код не может быть написан следующим образом (к которому я очень привык):
var someOtherArray = [];
for (var i = 0; i < array.length; i++) {
someOtherArray[i] = modifyObjetFromArray(array[i]);
}
Но это заставило меня задуматься.
Есть ли сценарий, когда написание такого цикла for имело бы смысл? Идея приходит в голову, что длина «массива» может измениться во время выполнения цикла for, но мы не хотим зацикливаться дальше, чем исходный размер, но я не могу представить себе такой сценарий.
Сокращение массива внутри цикла также не имеет особого смысла, потому что мы, вероятно, получим исключение OutOfBoundsException.
Есть ли известный шаблон проектирования, где эта аннотация полезна?
Редактировать Как отмечает @ Jerry101, причина в производительности. Вот ссылка на созданный мной тест производительности: http://jsperf.com/ninforloop . На мой взгляд, разница не достаточно велика, если вы не выполняете итерацию, хотя очень большой массив. Код, из которого я скопировал его, содержал до 20 элементов, так что я думаю, что читаемость в этом случае перевешивает оценку производительности.
источник
n
может быть медленнее, чем использование варианта,array.Length
поскольку JITter может не заметить, что он может устранить проверки границ массива.Ответы:
Переменная
n
гарантирует, что сгенерированный код не извлекает длину массива для каждой итерации.Это оптимизация, которая может иметь значение во время выполнения в зависимости от используемого языка, является ли массив фактически объектом коллекции или «массивом» JavaScript, и другими деталями оптимизации.
источник
n
циклом, что, как правило, хорошо. Я бы определил это до цикла, только если бы я хотел использовать его позже.Выборка длины массива может быть «более дорогой», чем фактическое действие, которое вы повторяете.
Так что если набор не меняется, запросите длину только один раз.
Не с массивами, а с наборами записей, поступающими с сервера sql, я увидел значительные улучшения, не запрашивая количество записей на каждой итерации. (конечно, делайте это, только если вы можете гарантировать, что массив или набор записей не будут изменены во время этого процесса).
источник
Люди, говорящие о производительности, вероятно, правы в том, что именно поэтому она была написана таким образом (человек, который написал ее таким образом, может быть не прав, что она существенно влияет на производительность, но это другой вопрос).
Однако, чтобы ответить на эту часть вашего вопроса, я думаю, что это, скорее всего, произойдет, когда основная цель цикла состоит в том, чтобы изменить массив, над которым он работает. Рассмотрим что-то вроде этого в псевдокоде:
Конечно, есть и другие способы написать это. В этом случае я мог бы проверить наличие плюсов одновременно с проверкой, приняли ли получатели свои приглашения, и создал полный список гостей по одному приглашению за раз. Я не обязательно хочу , чтобы объединить эти две операции, но я не могу сразу думать о причине , почему это определенно не так , и поэтому этот проект требуется . Это вариант для рассмотрения, иногда.
На самом деле, я думаю, что самое неправильное в этом коде состоит в том, что членство в
guests
массиве означает разные вещи в разных точках кода. Поэтому я, конечно, не назвал бы это «шаблоном», но я не знаю, что достаточно дефекта, чтобы исключить возможность что-либо делать в этом роде :-)источник
Если это вообще возможно, вы должны использовать итератор, который пересекает все элементы массива. Вы используете массив просто как последовательность, а не как хранилище с произвольным доступом, поэтому было бы очевидно, что итератор, который просто выполняет последовательный доступ, будет быстрее. Представьте, что вы думаете, что массив на самом деле является двоичным деревом, но кто-то написал код, который определяет «длину» путем подсчета элементов, и код, который обращается к i-му элементу, также путем обхода элемента, каждый в O (n ). Итератор может быть очень быстрым, ваш цикл будет замедленным.
источник