O'zbek

JavaScript Iterator Protokolini tushunish va joriy etish bo'yicha to'liq qo'llanma, ma'lumotlarni yaxshiroq boshqarish uchun maxsus iteratorlar yaratish imkonini beradi.

JavaScript Iterator Protokoli va Maxsus Iteratorlarni Tushunish

JavaScript'ning Iterator Protokoli ma'lumotlar tuzilmalarini aylanib o'tishning standartlashtirilgan usulini taqdim etadi. Ushbu protokolni tushunish dasturchilarga massivlar va satrlar kabi o'rnatilgan iteratsiya qilinadiganlar bilan samarali ishlash hamda maxsus ma'lumotlar tuzilmalari va dastur talablariga moslashtirilgan o'zlarining maxsus iteratsiya qilinadiganlarini yaratish imkonini beradi. Ushbu qo'llanma Iterator Protokolini va maxsus iteratorlarni qanday joriy etishni to'liq o'rganib chiqadi.

Iterator Protokoli nima?

Iterator Protokoli obyektning qanday qilib iteratsiya qilinishini, ya'ni uning elementlariga ketma-ket qanday kirish mumkinligini belgilaydi. U ikki qismdan iborat: Iteratsiya qilinadigan (Iterable) protokoli va Iterator protokoli.

Iteratsiya qilinadigan (Iterable) Protokoli

Agar obyektda Symbol.iterator kalitiga ega metod mavjud bo'lsa, u Iteratsiya qilinadigan (Iterable) hisoblanadi. Bu metod Iterator protokoliga mos keladigan obyektni qaytarishi kerak.

Mohiyatan, iteratsiya qilinadigan obyekt o'zi uchun iterator yaratishni biladi.

Iterator Protokoli

Iterator protokoli ketma-ketlikdan qiymatlarni qanday olishni belgilaydi. Agar obyektda ikkita xususiyatga ega obyektni qaytaruvchi next() metodi mavjud bo'lsa, u iterator hisoblanadi:

next() metodi Iterator protokolining asosiy ishchi qismidir. next() ga har bir murojaat iteratorni oldinga siljitadi va ketma-ketlikdagi keyingi qiymatni qaytaradi. Barcha qiymatlar qaytarilganda, next() done qiymati true ga o'rnatilgan obyektni qaytaradi.

O'rnatilgan Iteratsiya Qilinadiganlar

JavaScript o'zida bir nechta o'rnatilgan, tabiiy ravishda iteratsiya qilinadigan ma'lumotlar tuzilmalarini taqdim etadi. Bularga quyidagilar kiradi:

Ushbu iteratsiya qilinadiganlar for...of tsikli, yoyish sintaksisi (...) va Iterator Protokoliga tayanadigan boshqa konstruksiyalar bilan bevosita ishlatilishi mumkin.

Massivlar bilan misol:


const myArray = ["apple", "banana", "cherry"];

for (const item of myArray) {
  console.log(item); // Chiqish: apple, banana, cherry
}

Satrlar bilan misol:


const myString = "Hello";

for (const char of myString) {
  console.log(char); // Chiqish: H, e, l, l, o
}

for...of Tsikli

for...of tsikli iteratsiya qilinadigan obyektlarni aylanib chiqish uchun kuchli konstruksiyadir. U Iterator Protokolining murakkabliklarini avtomatik ravishda boshqaradi va ketma-ketlikdagi qiymatlarga kirishni osonlashtiradi.

for...of tsiklining sintaksisi:


for (const element of iterable) {
  // Har bir element uchun bajariladigan kod
}

for...of tsikli iteratsiya qilinadigan obyektdan iteratorni oladi (Symbol.iterator yordamida) va done true bo'lguncha iteratorning next() metodini qayta-qayta chaqiradi. Har bir iteratsiyada element o'zgaruvchisiga next() tomonidan qaytarilgan value xususiyati tayinlanadi.

Maxsus Iteratorlar Yaratish

JavaScript o'rnatilgan iteratsiya qilinadiganlarni taqdim etsa-da, Iterator Protokolining haqiqiy kuchi o'zingizning ma'lumotlar tuzilmalaringiz uchun maxsus iteratorlarni belgilash qobiliyatidadir. Bu sizning ma'lumotlaringizni qanday aylanib o'tishni va ularga qanday kirishni nazorat qilish imkonini beradi.

Maxsus iteratorni yaratish uchun quyidagi amallarni bajaring:

  1. Maxsus ma'lumotlar tuzilmangizni ifodalovchi sinf yoki obyektni aniqlang.
  2. Sinfingiz yoki obyektingizda Symbol.iterator metodini joriy eting. Bu metod iterator obyektini qaytarishi kerak.
  3. Iterator obyekti value va done xususiyatlariga ega obyektni qaytaruvchi next() metodiga ega bo'lishi kerak.

Misol: Oddiy Diapazon uchun Iterator Yaratish

Keling, sonlar diapazonini ifodalovchi Range deb nomlangan sinf yaratamiz. Biz diapazondagi sonlarni iteratsiya qilish uchun Iterator Protokolini joriy qilamiz.


class Range {
  constructor(start, end) {
    this.start = start;
    this.end = end;
  }

  [Symbol.iterator]() {
    let currentValue = this.start;
    const that = this; // Iterator obyekti ichida 'this' ni ishlatish uchun ushlab qolamiz

    return {
      next() {
        if (currentValue <= that.end) {
          return {
            value: currentValue++,
            done: false,
          };
        } else {
          return {
            value: undefined,
            done: true,
          };
        }
      },
    };
  }
}

const myRange = new Range(1, 5);

for (const number of myRange) {
  console.log(number); // Chiqish: 1, 2, 3, 4, 5
}

Tushuntirish:

Misol: Bog'langan Ro'yxat uchun Iterator Yaratish

Keling, yana bir misolni ko'rib chiqaylik: bog'langan ro'yxat ma'lumotlar tuzilmasi uchun iterator yaratish. Bog'langan ro'yxat - bu tugunlar ketma-ketligi bo'lib, har bir tugun qiymat va ro'yxatdagi keyingi tugunga havola (ko'rsatkich) saqlaydi. Ro'yxatdagi oxirgi tugun null (yoki undefined) ga ishora qiladi.


class LinkedListNode {
    constructor(value, next = null) {
        this.value = value;
        this.next = next;
    }
}

class LinkedList {
    constructor() {
        this.head = null;
    }

    append(value) {
        const newNode = new LinkedListNode(value);
        if (!this.head) {
            this.head = newNode;
            return;
        }

        let current = this.head;
        while (current.next) {
            current = current.next;
        }
        current.next = newNode;
    }

    [Symbol.iterator]() {
        let current = this.head;

        return {
            next() {
                if (current) {
                    const value = current.value;
                    current = current.next;
                    return {
                        value: value,
                        done: false
                    };
                } else {
                    return {
                        value: undefined,
                        done: true
                    };
                }
            }
        };
    }
}

// Ishlatish misoli:
const myList = new LinkedList();
myList.append("London");
myList.append("Paris");
myList.append("Tokyo");

for (const city of myList) {
    console.log(city); // Chiqish: London, Paris, Tokyo
}

Tushuntirish:

Generator Funksiyalari

Generator funksiyalari iteratorlarni yaratishning yanada ixcham va oqlangan usulini taqdim etadi. Ular talab bo'yicha qiymatlarni ishlab chiqarish uchun yield kalit so'zidan foydalanadilar.

Generator funksiyasi function* sintaksisi yordamida aniqlanadi.

Misol: Generator Funksiyasi yordamida Iterator Yaratish

Keling, Range iteratorini generator funksiyasi yordamida qayta yozamiz:


class Range {
  constructor(start, end) {
    this.start = start;
    this.end = end;
  }

  *[Symbol.iterator]() {
    for (let i = this.start; i <= this.end; i++) {
      yield i;
    }
  }
}

const myRange = new Range(1, 5);

for (const number of myRange) {
  console.log(number); // Chiqish: 1, 2, 3, 4, 5
}

Tushuntirish:

Generator funksiyalari next() metodini va done bayrog'ini avtomatik ravishda boshqarib, iterator yaratishni soddalashtiradi.

Misol: Fibonachchi Ketma-ketligi Generatori

Generator funksiyalaridan foydalanishning yana bir ajoyib misoli - Fibonachchi ketma-ketligini generatsiya qilish:


function* fibonacciSequence() {
  let a = 0;
  let b = 1;

  while (true) {
    yield a;
    [a, b] = [b, a + b]; // Bir vaqtning o'zida yangilash uchun destrukturizatsiya
  }
}

const fibonacci = fibonacciSequence();

for (let i = 0; i < 10; i++) {
  console.log(fibonacci.next().value); // Chiqish: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
}

Tushuntirish:

Iterator Protokolidan Foydalanishning Afzalliklari

Iteratorlarning Ilg'or Texnikalari

Iteratorlarni Birlashtirish

Siz bir nechta iteratorni bitta iteratorga birlashtirishingiz mumkin. Bu bir nechta manbadan olingan ma'lumotlarni yagona usulda qayta ishlash kerak bo'lganda foydalidir.


function* combineIterators(...iterables) {
  for (const iterable of iterables) {
    for (const item of iterable) {
      yield item;
    }
  }
}

const array1 = [1, 2, 3];
const array2 = ["a", "b", "c"];
const string1 = "XYZ";

const combined = combineIterators(array1, array2, string1);

for (const value of combined) {
  console.log(value); // Chiqish: 1, 2, 3, a, b, c, X, Y, Z
}

Ushbu misolda `combineIterators` funksiyasi argument sifatida istalgan miqdordagi iteratsiya qilinadiganlarni qabul qiladi. U har bir iteratsiya qilinadiganni aylanib chiqadi va har bir elementni qaytaradi. Natijada barcha kiruvchi iteratsiya qilinadiganlardan olingan barcha qiymatlarni ishlab chiqaradigan yagona iterator hosil bo'ladi.

Iteratorlarni Filtrlash va O'zgartirish

Siz boshqa iterator tomonidan ishlab chiqarilgan qiymatlarni filtrlash yoki o'zgartiradigan iteratorlar ham yaratishingiz mumkin. Bu ma'lumotlarni quvur shaklida qayta ishlashga imkon beradi, bunda har bir qiymat generatsiya qilinishi bilan unga turli operatsiyalar qo'llaniladi.


function* filterIterator(iterable, predicate) {
  for (const item of iterable) {
    if (predicate(item)) {
      yield item;
    }
  }
}

function* mapIterator(iterable, transform) {
  for (const item of iterable) {
    yield transform(item);
    }
}

const numbers = [1, 2, 3, 4, 5, 6];

const evenNumbers = filterIterator(numbers, (x) => x % 2 === 0);
const squaredEvenNumbers = mapIterator(evenNumbers, (x) => x * x);

for (const value of squaredEvenNumbers) {
    console.log(value); // Chiqish: 4, 16, 36
}

Bu yerda `filterIterator` iteratsiya qilinadigan va predikat funksiyasini qabul qiladi. U faqat predikat `true` qaytargan elementlarni qaytaradi. `mapIterator` esa iteratsiya qilinadigan va o'zgartirish funksiyasini qabul qiladi. U har bir elementga o'zgartirish funksiyasini qo'llash natijasini qaytaradi.

Haqiqiy Hayotdagi Qo'llanilishlar

Iterator Protokoli JavaScript kutubxonalari va freymvorklarida keng qo'llaniladi va u turli xil haqiqiy hayotiy dasturlarda, ayniqsa katta hajmdagi ma'lumotlar to'plamlari yoki asinxron operatsiyalar bilan ishlashda qimmatlidir.

Eng Yaxshi Amaliyotlar

Xulosa

JavaScript Iterator Protokoli ma'lumotlar tuzilmalarini aylanib o'tishning kuchli va moslashuvchan usulini taqdim etadi. Iteratsiya qilinadigan va Iterator protokollarini tushunib, generator funksiyalaridan foydalangan holda, siz o'zingizning maxsus ehtiyojlaringizga moslashtirilgan maxsus iteratorlarni yaratishingiz mumkin. Bu sizga ma'lumotlar bilan samarali ishlash, kodning o'qilishini yaxshilash va dasturlaringizning samaradorligini oshirish imkonini beradi. Iteratorlarni o'zlashtirish JavaScript imkoniyatlarini chuqurroq tushunishga yordam beradi va sizga yanada oqlangan va samarali kod yozish imkonini beradi.