Лучшие практики для циклов for в TypeScript

Лучшие практики для циклов for в TypeScript

Эта статья объясняет лучшие практики использования циклов for в TypeScript.

YouTube Video

Лучшие практики для циклов for в TypeScript

Инструкция for является основным и мощным синтаксисом для выполнения повторяющихся операций. В TypeScript использование типобезопасности и написание кода с учетом его читаемости и поддерживаемости позволяет создавать эффективный код с меньшим количеством ошибок.

Выбор подходящего типа цикла

TypeScript предлагает несколько конструкций циклов, каждая из которых подходит для различных случаев использования. Выбор подходящего цикла имеет решающее значение для ясности и производительности кода.

Стандартный цикл for

1for (let i = 0; i < 10; i++) {
2    console.log(i);
3}

Стандартный цикл for идеален, когда вам нужен точный контроль над индексом итерации.

Лучшие практики
1const maxIterations = 10;
2for (let i = 0; i < maxIterations; i++) {
3    console.log(i);
4}

При написании инструкций for соблюдение следующих рекомендаций поможет вам писать более безопасный и читаемый код.

  • Используйте let для переменных индекса
    • Использование let вместо var ограничивает область видимости блоком, предотвращая непреднамеренное поведение.
  • Используйте константы и описательные имена переменных, чтобы сделать границы цикла явными.
    • Избегайте «магических чисел» и используйте осмысленные имена переменных, чтобы улучшить читаемость.

Цикл for...of

1const array = [1, 2, 3];
2for (let value of array) {
3    console.log(value);
4}

Цикл for...of подходит для перебора итерируемых объектов, таких как массивы и строки.

Лучшие практики
1const array = [1, 2, 3];
2for (const value of array) {
3    console.log(value);
4}

При написании циклов for...of учет следующих моментов поможет вам писать более безопасный код.

  • Используйте const для переменных цикла
    • Если значения не изменяются внутри цикла, использование const помогает предотвратить случайное переназначение.

Цикл for...in

1const obj = { a: 1, b: 2, c: 3 };
2for (const key in obj) {
3    console.log(`${key}: ${obj[key]}`);
4}

Цикл for...in перебирает перечисляемые свойства объекта.

Лучшие практики
1const obj = { a: 1, b: 2, c: 3 };
2for (const key in obj) {
3    if (obj.hasOwnProperty(key)) {
4        console.log(`${key}: ${obj[key]}`);
5    }
6}

При написании цикла for...in вы можете учитывать следующие моменты.

  • Фильтруйте свойства
    • Если вам нужно избежать унаследованных свойств, вы можете использовать hasOwnProperty.
  • Не используйте for...in для массивов. Избегайте использования for...in для массивов. Это может привести к перебору всех перечисляемых свойств, включая те, которые не являются индексами массива.

Метод forEach

1const array = [1, 2, 3];
2array.forEach((value, index) => {
3    console.log(`Index: ${index}, Value: ${value}`);
4});

При переборе массивов forEach является лаконичным и избавляет от необходимости управлять индексами.

Лучшие практики

При использовании метода forEach вы можете учитывать следующие моменты.

  • Используйте стрелочные функции
    • Используйте лаконичные стрелочные функции, чтобы улучшить читаемость.
  • Избегайте прерываний
    • forEach не поддерживает break или continue. Используйте циклы for...of или for, когда это необходимо:.

Безопасность типов и предотвращение ошибок

Используя систему типов TypeScript, вы можете предотвратить ошибки во время выполнения итерации:.

Определяйте строгие типы для переменных цикла

1const items = [1, 2, 3];
2items.forEach(item => {
3    console.log(item * 2);
4});
1const items: number[] = [1, 2, 3];
2items.forEach((item: number) => {
3    console.log(item * 2);
4});

Явно задавая типы для переменных цикла, вы можете заранее обнаружить несоответствия типов.

Избегайте неявного использования any

1{
2  "compilerOptions": {
3    "noImplicitAny": true
4  }
5}

Кроме того, включив параметр noImplicitAny в файле tsconfig.json, вы можете предотвратить неявное присваивание переменным без явного типа типа any.

Используйте ReadonlyArray, когда это необходимо

1const numbers: ReadonlyArray<number> = [1, 2, 3];
2for (const value of numbers) {
3    console.log(value);
4}

Если вы итерируете массив, который не должен изменяться, вы можете использовать ReadonlyArray.

Соображения производительности

Эффективность имеет решающее значение для циклов, обрабатывающих большие объемы данных или часто выполняющихся циклов:.

Выберите оптимальный метод реализации цикла.

Существует множество способов реализации циклов, каждый из которых отличается читаемостью и эффективностью выполнения.

 1// Prepare input data (an array from 1 to 1000000)
 2const input: number[] = Array.from({ length: 1000000 }, (_, i) => i + 1);
 3
 4// --- for ---
 5console.time('for loop');
 6const squaresFor: number[] = [];
 7for (let i = 0; i < input.length; i++) {
 8    squaresFor.push(input[i] * input[i]);
 9}
10console.timeEnd('for loop');
11
12// --- while ---
13console.time('while loop');
14const squaresWhile: number[] = [];
15let i: number = 0;
16while (i < input.length) {
17    squaresWhile.push(input[i] * input[i]);
18    i++;
19}
20console.timeEnd('while loop');
21
22// --- for-of ---
23console.time('for-of loop');
24const squaresForOf: number[] = [];
25for (const num of input) {
26    squaresForOf.push(num * num);
27}
28console.timeEnd('for-of loop');
29
30// --- forEach ---
31console.time('forEach loop');
32const squaresForEach: number[] = [];
33input.forEach((num: number): void => {
34    squaresForEach.push(num * num);
35});
36console.timeEnd('forEach loop');
37
38// --- map ---
39console.time('map');
40const squaresMap: number[] = input.map((value: number): number => value * value);
41console.timeEnd('map');

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

Используйте встроенные методы итерации

 1const squares = [1, 2, 3].map(value => value * value);
 2console.log(squares);
 3
 4const numbers = [1, 2, 3, 4, 5, 6];
 5const evenNumbers = numbers.filter(value => value % 2 === 0);
 6console.log(evenNumbers); // [2, 4, 6]
 7
 8const squaredEvens = numbers
 9    .filter(value => value % 2 === 0) // Keep only even numbers
10    .map(value => value * value);     // Square the remaining values
11
12console.log(squaredEvens); // [4, 16, 36]

Методы, такие как map и filter, в некоторых случаях могут быть более читаемыми.

Предпочитайте for...of для улучшения читаемости

Производительность должна становиться приоритетом только в ограниченных случаях; в целом, написание читаемого кода более важно. Например, приоритизация for...of может улучшить читаемость.

1const fruits = ["apple", "banana", "cherry"];
2
3for (let i = 0; i < fruits.length; i++) {
4    console.log(`${i}: ${fruits[i]}`);
5}
Лучшие практики
1const fruits = ["apple", "banana", "cherry"];
2
3for (const [index, fruit] of fruits.entries()) {
4    console.log(`${index}: ${fruit}`);
5}

Отдавая приоритет циклам for...of, вы можете писать более читаемый и устойчивый к ошибкам код. Как показано в этом примере, если вам также нужны индексы массива, эффективно объединять entries() с for...of.

Избегание распространенных ошибок

Изменение коллекций во время итерации

1const array = [1, 2, 3];
2for (const value of [...array]) {
3    if (value === 2) {
4        array.push(4); // Avoid this!
5    }
6}
7console.log(array);

Изменение массива во время итерации может привести к непредвиденному поведению:. При необходимости используйте копию.

Учитывайте граничные случаи

1const array: number[] = [];
2for (const value of array) {
3    console.log(value); // No output, but no errors
4}

Этот код работает нормально, но если вам нужно обработать пустые массивы, вы можете улучшить его следующим образом.

1const array: number[] = [];
2if (array.length === 0) {
3    console.log("The array is empty.");
4} else {
5    for (const value of array) {
6        console.log(value);
7    }
8}

Учет граничных случаев может помочь предотвратить ошибки в последующем коде.

Заключение

Чтобы овладеть оператором for в TypeScript, важно понять различные конструкции циклов, соблюдать практики безопасности типов и оптимизировать производительность. Эти лучшие практики помогут вам писать более чистый, надежный и легко сопровождаемый код.

Вы можете следовать этой статье, используя Visual Studio Code на нашем YouTube-канале. Пожалуйста, также посмотрите наш YouTube-канал.

YouTube Video