Когда я был в неведении и невежестве, когда мне задавали этот вопрос, в голове было пусто, потому что когда-то я думал, что forEach — это просто синтаксический сахар, созданный для удобства написания, и он часто использовался в бизнес-коде, но я не подумайте о его проблемах.Эта статья Цель состоит в том, чтобы записать ваше собственное ментальное путешествие, чтобы дать вам подсказку, если это поможет вам, это будет еще лучше.
Итак, вернемся к заголовку, прежде всего forEachНе могу использовать никакие средства, чтобы вырваться из циклаДа, инспектор, который хочет знать ответ на вопрос, может в это время прекратить чтение.
Зачем? Мы знаем, что forEach получает функцию, которая обычно имеет два параметра, первый — это текущий элемент цикла, а второй — индекс, соответствующий элементу.Вручную реализуем псевдокод:
Array.prototype.myForEach = function (fn) {
for (let i = 0; i < this.length; i++) {
fn(this[i], i, this);
}
}
Я не знаю, действительно ли forEach реализован таким образом, но приведенный выше простой псевдокод действительно удовлетворяет характеристикам forEach, а также очевидно, что он не может выскочить из цикла, потому что нет возможности оперировать настоящим для тела цикла.
Позже, ознакомившись с документацией, я обнаружил, что официальное определение forEach, на мой взгляд, не является синтаксическим сахаром.Его стандартное утверждение состоит в том, что forEach выполняет предоставленную вами функцию один раз для каждого элемента массива. В официальном документе также есть этот абзац:
Невозможно остановить или разорвать цикл, кроме создания исключения. Если вам нужно такое поведение, метод forEach() — неправильный инструмент.
Используйте исключение throw, чтобы выйти из цикла foreach
let arr = [0, 1, "stop", 3, 4];
try {
arr.forEach(element => {
if (element === "stop") {
throw new Error("forEachBreak");
}
console.log(element); // 输出 0 1 后面不输出
});
} catch (e) {
console.log(e.message); // forEachBreak
};
Итак, можете ли вы подумать, что forEach может выйти из цикла и использовать генерацию исключений? Я думаю, доброжелательный видит благожелательный, а мудрый видит мудрость.В конструкции forEach нет конструкции прерывания цикла, а при использовании пакета try-catch, когдаЕсли тело цикла слишком большое, производительность ухудшится., это неизбежно, поэтому генерация исключений может использоваться как средство прерывания forEach, но это не панацея для решения проблемы forEach.
Снова вернитесь к псевдокоду, написанному в начале, внесите в него некоторые оптимизации и добавьте оценку входящей функции в реальный цикл for:
// 为避免争议此处不再覆写原有forEach函数
Array.prototype.myForEach = function (fn) {
for (let i = 0; i < this.length; i++) {
let ret = fn(this[i], i, this);
if (typeof ret !== "undefined" && (ret == null || ret == false)) break;
}
}
Таким образом, цикл можно прервать в соответствии с возвращаемым значением:
let arr = [0, 1, "stop", 3, 4];
arr.myForEach(x => {
if (x === 'stop') return false
console.log(x); // 输出 0 1 后面不输出
});
// return即为continue:
arr.myForEach(x => {
if (x === 'stop') return
console.log(x); // 0 1 3 4
});
В документации также упоминается forEachнужна функция синхронизации, то есть при использовании асинхронных функций или Promise в качестве обратных вызовов будут возникать неожиданные результаты, поэтому forEach по-прежнему нужно использовать с осторожностью.
Конечно, использование простого цикла for для завершения всего — тоже способ,Код сначала пишется для того, чтобы люди могли его увидеть, что дает возможность запускать его на машине., forEach во многих случаях проще в использовании, но мы также должны писать наш бизнес-код, исходя из понимания того, как JS проектирует эти функции инструмента.
Мы можем использовать при переборе массиваfor..of..
, используется при переборе объектовfor..in..
, а официальный также перечисляет некоторые другие функции инструмента в документе forEach, поэтому я не буду здесь слишком подробно останавливаться:
Array.prototype.find()
Array.prototype.findIndex()
Array.prototype.map()
Array.prototype.filter()
Array.prototype.every()
Array.prototype.some()
Как выбрать и использовать соответствующие функции инструмента для более эффективной обработки бизнес-логики в соответствии с различными бизнес-сценариями — это то, о чем мы действительно должны подумать, возможно, это то, что мы действительно хотим исследовать на собеседовании.