Столько циклов в js,for
for...in
for...of
forEach
, некоторые циклы кажутся похожимиfor
петля иforEach
разница.
Мы обсуждаем с нескольких сторон:
-
for
петля иforEach
существенная разница. -
for
петля иforEach
грамматические различия. -
for
петля иforEach
разница в производительности.
Существенная разница
for
Цикл — это циклический метод, который существовал, когда был предложен js.forEach
Он предложен ES5 и монтируется на прототипе итерируемых объектов, таких какArray
Set
Map
.
forEach
是一个迭代器,负责遍历可迭代对象。 Тактраверс,повторять,повторяемый объектКакие соответственно.
траверс: Относится к каждому члену структуры данных и поведению регулярно при первом посещении.
повторять: итерация — это особая форма рекурсии, метод, предоставляемый итераторами, по умолчанию в определенном порядке.по одномуДоступ к членам структуры данных. Итерация также является поведением обхода.
повторяемый объект: введено в ES6iterable
Типы,Array
Set
Map
String
arguments
NodeList
принадлежатьiterable
, они имеют характеристику[Symbol.iterator]
метод, объект, содержащий его, считается итерируемымiterable
.
Узнав этиforEach
По сути, это итератор, связанный сfor
Существенная разница между циклами заключается в том, чтоforEach
отвечает за обход(Array
Set
Map
) итерируемых объектов, аfor
Цикл — это циклический механизм, который просто проходит через массив.
Давайте поговорим о том, что естьитератор, помните ранее упомянутоеГенератор генераторКогда он вызывается, генерирует объект iTerator (объект iTerator), он имеет.next()
метод, который возвращает объект за вызов{value:value,done:Boolean}
,value
то, что возвращаетсяyield
После возвращаемого значения, когдаyield
конец,done
сталиtrue
, вызывая и выполняя последовательные итерации для доступа к внутреннему значению.
итераторявляется особым объектом. В спецификации ES6 его флаг должен возвращать объектnext()
метод, итеративное поведение оценивается вdone
среди. Итераторы реализуют обход без раскрытия внутреннего представления. см. код
let arr = [1, 2, 3, 4] // 可迭代对象
let iterator = arr[Symbol.iterator]() // 调用 Symbol.iterator 后生成了迭代器对象
console.log(iterator.next()); // {value: 1, done: false} 访问迭代器对象的next方法
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: 4, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
Мы видели это. Пока это итерируемый объект, вызовите внутреннийSymbol.iterator
предоставит итератор и вернет в соответствии с итераторомnext
метод доступа к внутренностям, который такжеfor...of
принцип реализации.
let arr = [1, 2, 3, 4]
for (const item of arr) {
console.log(item); // 1 2 3 4
}
Звонокnext
метод возвращает объектvalue
значение и хранится вitem
в, покаdone
дляtrue
Вырваться из цикла, доступны все итерируемые объектыfor...of
Потребление. Давайте посмотрим на другие итерируемые объекты:
function num(params) {
console.log(arguments); // Arguments(6) [1, 2, 3, 4, callee: ƒ, Symbol(Symbol.iterator): ƒ]
let iterator = arguments[Symbol.iterator]()
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: 4, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
}
num(1, 2, 3, 4)
let set = new Set('1234')
set.forEach(item => {
console.log(item); // 1 2 3 4
})
let iterator = set[Symbol.iterator]()
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: 4, done: false}
console.log(iterator.next()); // {value: undefined, done: true}
Таким образом, мы также можем интуитивно видеть итерируемые объекты вSymbol.iterator
Итераторы могут генерироваться при вызове свойств, иforEach
Он также генерирует итератор, передавая значение каждого элемента во внутреннюю функцию обратного вызова.
(Заинтересованные студенты могут искатьforEach
исходный код,Array
Set
Map
установлен на экземпляреforEach
, но большинство ответов в Интернете можно получить черезlength
Судя по длине, используяfor
Реализован петлевой механизм. но вSet
Map
Его использование сообщит об ошибке, поэтому я думаю, что это итератор вызова, который продолжает вызыватьnext
, который передается в функцию обратного вызова. Так как я не нашел ответ в сети, я не могу делать никаких утверждений.Те, у кого есть ответ, могут оставить мне сообщение в области комментариев)
for
петля иforEach
грамматические различия
Зная существенную разницу, в чем грамматическая разница между ними в процессе подачи заявки?
-
forEach
параметр. -
forEach
прерывание. -
forEach
Удалить собственный элемент, индекс не может быть сброшен. -
for
Циклы могут контролировать начальную точку цикла.
forEach
параметры
мы действительно понимаемforEach
полный справочный контент? Это выглядит так:
arr.forEach((self,index,arr) =>{},this)
себя:Элементы, пройденные в данный момент в массиве По умолчанию элементы массива получаются в порядке слева направо.
показатель:Индекс текущего элемента массива, индекс первого элемента равен 0 и так далее.
прибытие:Текущий пройденный массив.
это:Это указывает на функцию обратного вызова.
let arr = [1, 2, 3, 4];
let person = {
name: '技术直男星辰'
};
arr.forEach(function (self, index, arr) {
console.log(`当前元素为${self}索引为${index},属于数组${arr}`);
console.log(this.name+='真帅');
}, person)
мы можем использоватьarr
Реализовать дедупликацию массива:
let arr1 = [1, 2, 1, 3, 1];
let arr2 = [];
arr1.forEach(function (self, index, arr) {
arr1.indexOf(self) === index ? arr2.push(self) : null;
});
console.log(arr2); // [1,2,3]
forEach
прерывание
в js естьbreak
return
continue
Чтобы прервать или выйти из функции, мы находимся вfor
Цикл будет использоваться в некоторых нарушениях поведения, ищите оптимизацию обхода массива, это хорошо, но посколькуforEach
Это итератор, и его можно пройти только по порядку, поэтому описанное выше поведение прерывания не поддерживается.
let arr = [1, 2, 3, 4],
i = 0,
length = arr.length;
for (; i < length; i++) {
console.log(arr[i]); //1,2
if (arr[i] === 2) {
break;
};
};
arr.forEach((self,index) => {
console.log(self);
if (self === 2) {
break; //报错
};
});
arr.forEach((self,index) => {
console.log(self);
if (self === 2) {
continue; //报错
};
});
если я долженforEach
Как насчет того, чтобы выпрыгнуть из петли? На самом деле есть способ,try/catch
:
try {
var arr = [1, 2, 3, 4];
arr.forEach(function (item, index) {
//跳出条件
if (item === 3) {
throw new Error("LoopTerminates");
}
//do something
console.log(item);
});
} catch (e) {
if (e.message !== "LoopTerminates") throw e;
};
Если вы столкнетесьreturn
Он не сообщит об ошибке, но не вступит в силу
let arr = [1, 2, 3, 4];
function find(array, num) {
array.forEach((self, index) => {
if (self === num) {
return index;
};
});
};
let index = find(arr, 2);// undefined
forEach
Удалить собственный элемент, индекс не может быть сброшен
существуетforEach
у нас нет контроляindex
Значение , оно будет бездумно увеличиваться только до тех пор, пока не превысит размер массива.length
Вырваться из петли. Так что он не может удалить себяindex
Сброс, давайте рассмотрим простой пример:
let arr = [1,2,3,4]
arr.forEach((item, index) => {
console.log(item); // 1 2 3 4
index++;
});
index
Он не изменяется при добавлении или удалении из тела функции. В реальной разработке очень часто приходится перемещаться по массиву при удалении элемента.forEach
Будьте осторожны при удалении.
for
Циклы могут контролировать начальную точку цикла
как указано вышеforEach
Начальная точка цикла может быть только 0 без вмешательства человека, иfor
Цикл отличается:
let arr = [1, 2, 3, 4],
i = 1,
length = arr.length;
for (; i < length; i++) {
console.log(arr[i]) // 2 3 4
};
Предыдущая операция обхода массива и удаления размножения может быть записана как
let arr = [1, 2, 1],
i = 0,
length = arr.length;
for (; i < length; i++) {
// 删除数组中所有的1
if (arr[i] === 1) {
arr.splice(i, 1);
//重置i,否则i会跳一位
i--;
};
};
console.log(arr); // [2]
//等价于
var arr1 = arr.filter(index => index !== 1);
console.log(arr1) // [2]
for
петля иforEach
разница в производительности
Что касается сравнения производительности, мы добавляемmap
итератор, который аналогиченfilter
То же самое для создания нового массива. мы сравниваемfor
forEach
map
Как выглядит производительность в среде браузера:
Сравнение производительности: for > forEach > карта
В Chrome 62 и Node.js v9.1.0:for
коэффициент циклаforEach
в 1 раз быстрее,forEach
Сравниватьmap
Около 20% быстрее.Анализ причин
for
: Цикл for не имеет дополнительного стека вызовов функций и контекста, поэтому его реализация наиболее проста.
forEach
: Для forEach сигнатура его функции содержит параметры и контекст, поэтому производительность будет ниже, чем уfor
цикл.
map
:map
Самая медленная причина в том, чтоmap
Будет возвращен новый массив, а создание и назначение массива приведет к выделению пространства памяти, что приведет к большим потерям производительности. еслиmap
Вложенный в цикл, он приведет к большему ненужному потреблению памяти.
Когда вы используете итератор для обхода массива, если вам не нужно возвращать новый массив, а использоватьmap
Это противоречит первоначальному замыслу дизайна. В моей разработке интерфейса я видел, как многие люди просто использовали его для обхода массива.map
из:
let data = [];
let data2 = [1,2,3];
data2.map(item=>data.push(item));
Написано в конце: Это вопрос, с которым я столкнулся в интервью, когда знал только грамматическую разницу. не изповторяемый объект,итератор,Строительа такжепредставление, а также различать сходства и различия между ними с разных точек зрения. Я также надеюсь, что смогу разработать простой вопрос с разных точек зрения, чтобы каждый мог его полностью понять.
Если эта статья полезна или поучительна для вас, я очень рад