தமிழ்

ஜாவாஸ்கிரிப்ட் இட்டரேட்டர் புரோட்டோகாலைப் புரிந்துகொண்டு செயல்படுத்துவதற்கான ஒரு விரிவான வழிகாட்டி. இது மேம்பட்ட தரவு கையாளுதலுக்காக தனிப்பயன் இட்டரேட்டர்களை உருவாக்க உங்களுக்கு உதவும்.

ஜாவாஸ்கிரிப்ட் இட்டரேட்டர் புரோட்டோகால் மற்றும் தனிப்பயன் இட்டரேட்டர்களைப் பற்றிய விளக்கம்

ஜாவாஸ்கிரிப்டின் இட்டரேட்டர் புரோட்டோகால், தரவுக் கட்டமைப்புகளை வரிசையாகப் பெறுவதற்கு ஒரு தரப்படுத்தப்பட்ட வழியை வழங்குகிறது. இந்த புரோட்டோகாலைப் புரிந்துகொள்வது, டெவலப்பர்களுக்கு உள்ளமைக்கப்பட்ட இட்டரபிள்களான (iterables) அரேக்கள் (arrays) மற்றும் ஸ்டிரிங்ஸ் (strings) போன்றவற்றுடன் திறமையாக வேலை செய்யவும், குறிப்பிட்ட தரவுக் கட்டமைப்புகள் மற்றும் பயன்பாட்டுத் தேவைகளுக்கு ஏற்ப தங்கள் சொந்த தனிப்பயன் இட்டரபிள்களை உருவாக்கவும் உதவுகிறது. இந்த வழிகாட்டி, இட்டரேட்டர் புரோட்டோகால் மற்றும் தனிப்பயன் இட்டரேட்டர்களை எவ்வாறு செயல்படுத்துவது என்பது பற்றிய விரிவான ஆய்வை வழங்குகிறது.

இட்டரேட்டர் புரோட்டோகால் என்றால் என்ன?

ஒரு ஆப்ஜெக்டை எவ்வாறு இட்டரேட் (iterate) செய்வது, அதாவது அதன் கூறுகளை எவ்வாறு வரிசையாக அணுகுவது என்பதை இட்டரேட்டர் புரோட்டோகால் வரையறுக்கிறது. இது இரண்டு பகுதிகளைக் கொண்டுள்ளது: இட்டரபிள் (Iterable) புரோட்டோகால் மற்றும் இட்டரேட்டர் (Iterator) புரோட்டோகால்.

இட்டரபிள் புரோட்டோகால்

ஒரு ஆப்ஜெக்டில் Symbol.iterator என்ற கீ (key) உடன் ஒரு மெத்தட் இருந்தால் அது இட்டரபிள் என்று கருதப்படுகிறது. இந்த மெத்தட், இட்டரேட்டர் புரோட்டோகாலுக்கு இணங்க ஒரு ஆப்ஜெக்டைத் திருப்பித் தர வேண்டும்.

சுருக்கமாக, ஒரு இட்டரபிள் ஆப்ஜெக்ட் தனக்கான ஒரு இட்டரேட்டரை எப்படி உருவாக்குவது என்பதை அறிந்திருக்கிறது.

இட்டரேட்டர் புரோட்டோகால்

இட்டரேட்டர் புரோட்டோகால் ஒரு வரிசையிலிருந்து மதிப்புகளை எவ்வாறு பெறுவது என்பதை வரையறுக்கிறது. ஒரு ஆப்ஜெக்டில் இரண்டு பண்புகளை (properties) கொண்ட ஒரு ஆப்ஜெக்டைத் திருப்பியளிக்கும் next() மெத்தட் இருந்தால் அது ஒரு இட்டரேட்டர் என்று கருதப்படுகிறது:

next() மெத்தட் தான் இட்டரேட்டர் புரோட்டோகாலின் முக்கியப் பகுதி. next()-க்கான ஒவ்வொரு அழைப்பும் இட்டரேட்டரை முன்னேற்றி, வரிசையில் உள்ள அடுத்த மதிப்பைக் கொடுக்கும். அனைத்து மதிப்புகளும் திருப்பியளிக்கப்பட்டதும், next() மெத்தட் done என்பதை true ஆகக் கொண்ட ஒரு ஆப்ஜெக்டைத் திருப்பியளிக்கும்.

உள்ளமைக்கப்பட்ட இட்டரபிள்கள்

ஜாவாஸ்கிரிப்ட் இயல்பாகவே இட்டரபிள்களாக இருக்கும் பல உள்ளமைக்கப்பட்ட தரவுக் கட்டமைப்புகளை வழங்குகிறது. அவற்றில் சில:

இந்த இட்டரபிள்களை for...of லூப், ஸ்ப்ரெட் சிண்டாக்ஸ் (...), மற்றும் இட்டரேட்டர் புரோட்டோகாலைச் சார்ந்த பிற கட்டமைப்புகளுடன் நேரடியாகப் பயன்படுத்தலாம்.

அரேக்களுடன் உதாரணம்:


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

for (const item of myArray) {
  console.log(item); // வெளியீடு: apple, banana, cherry
}

ஸ்டிரிங்ஸுடன் உதாரணம்:


const myString = "Hello";

for (const char of myString) {
  console.log(char); // வெளியீடு: H, e, l, l, o
}

for...of லூப்

for...of லூப் என்பது இட்டரபிள் ஆப்ஜெக்ட்களை இட்டரேட் செய்வதற்கான ஒரு சக்திவாய்ந்த கட்டமைப்பாகும். இது இட்டரேட்டர் புரோட்டோகாலின் சிக்கல்களை தானாகவே கையாளுகிறது, இதனால் ஒரு வரிசையில் உள்ள மதிப்புகளை அணுகுவது எளிதாகிறது.

for...of லூப்பின் சிண்டாக்ஸ்:


for (const element of iterable) {
  // ஒவ்வொரு உறுப்புக்கும் இயக்கப்பட வேண்டிய குறியீடு
}

for...of லூப், இட்டரபிள் ஆப்ஜெக்டிலிருந்து இட்டரேட்டரைப் பெறுகிறது (Symbol.iterator ஐப் பயன்படுத்தி), மற்றும் இட்டரேட்டரின் next() மெத்தடை done என்பது true ஆகும் வரை மீண்டும் மீண்டும் அழைக்கிறது. ஒவ்வொரு இட்டரேஷனிலும், element வேரியபிளுக்கு next() மூலம் திருப்பியளிக்கப்பட்ட value பண்பு ஒதுக்கப்படும்.

தனிப்பயன் இட்டரேட்டர்களை உருவாக்குதல்

ஜாவாஸ்கிரிப்ட் உள்ளமைக்கப்பட்ட இட்டரபிள்களை வழங்கினாலும், இட்டரேட்டர் புரோட்டோகாலின் உண்மையான சக்தி உங்கள் சொந்த தரவுக் கட்டமைப்புகளுக்கு தனிப்பயன் இட்டரேட்டர்களை வரையறுக்கும் திறனில் உள்ளது. இது உங்கள் தரவு எவ்வாறு வரிசையாகப் பெறப்படுகிறது மற்றும் அணுகப்படுகிறது என்பதைக் கட்டுப்படுத்த உங்களை அனுமதிக்கிறது.

ஒரு தனிப்பயன் இட்டரேட்டரை உருவாக்குவது எப்படி என்பது இங்கே:

  1. உங்கள் தனிப்பயன் தரவுக் கட்டமைப்பைக் குறிக்கும் ஒரு கிளாஸ் (class) அல்லது ஆப்ஜெக்டை வரையறுக்கவும்.
  2. உங்கள் கிளாஸ் அல்லது ஆப்ஜெக்டில் Symbol.iterator மெத்தடை செயல்படுத்தவும். இந்த மெத்தட் ஒரு இட்டரேட்டர் ஆப்ஜெக்டைத் திருப்பியளிக்க வேண்டும்.
  3. அந்த இட்டரேட்டர் ஆப்ஜெக்டில், value மற்றும் done பண்புகளுடன் ஒரு ஆப்ஜெக்டைத் திருப்பியளிக்கும் next() மெத்தட் இருக்க வேண்டும்.

உதாரணம்: ஒரு எளிய வரம்பிற்கு (Range) இட்டரேட்டர் உருவாக்குதல்

எண்களின் வரம்பைக் குறிக்கும் Range என்ற கிளாஸை உருவாக்குவோம். அந்த வரம்பில் உள்ள எண்களை இட்டரேட் செய்ய அனுமதிப்பதற்காக இட்டரேட்டர் புரோட்டோகாலை செயல்படுத்துவோம்.


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

  [Symbol.iterator]() {
    let currentValue = this.start;
    const that = this; // இட்டரேட்டர் ஆப்ஜெக்டின் உள்ளே பயன்படுத்த 'this' ஐப் பிடிக்கவும்

    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); // வெளியீடு: 1, 2, 3, 4, 5
}

விளக்கம்:

உதாரணம்: ஒரு லிங்க்ட் லிஸ்டுக்கு (Linked List) இட்டரேட்டர் உருவாக்குதல்

மற்றொரு உதாரணத்தைக் கருத்தில் கொள்வோம்: ஒரு லிங்க்ட் லிஸ்ட் தரவுக் கட்டமைப்புக்கு இட்டரேட்டர் உருவாக்குதல். ஒரு லிங்க்ட் லிஸ்ட் என்பது நோட்களின் (nodes) ஒரு வரிசையாகும், இதில் ஒவ்வொரு நோடும் ஒரு மதிப்பையும், பட்டியலிலுள்ள அடுத்த நோடுக்கு ஒரு குறிப்பையும் (pointer) கொண்டிருக்கும். பட்டியலின் கடைசி நோடு null (அல்லது undefined) க்கு ஒரு குறிப்பைக் கொண்டிருக்கும்.


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
                    };
                }
            }
        };
    }
}

// உதாரணப் பயன்பாடு:
const myList = new LinkedList();
myList.append("London");
myList.append("Paris");
myList.append("Tokyo");

for (const city of myList) {
    console.log(city); // வெளியீடு: London, Paris, Tokyo
}

விளக்கம்:

ஜெனரேட்டர் ஃபங்ஷன்கள் (Generator Functions)

ஜெனரேட்டர் ஃபங்ஷன்கள் இட்டரேட்டர்களை உருவாக்குவதற்கு மிகவும் சுருக்கமான மற்றும் நேர்த்தியான வழியை வழங்குகின்றன. அவை தேவைக்கேற்ப மதிப்புகளை உருவாக்க yield என்ற கீவேர்டைப் பயன்படுத்துகின்றன.

ஒரு ஜெனரேட்டர் ஃபங்ஷன் function* சிண்டாக்ஸைப் பயன்படுத்தி வரையறுக்கப்படுகிறது.

உதாரணம்: ஜெனரேட்டர் ஃபங்ஷனைப் பயன்படுத்தி இட்டரேட்டர் உருவாக்குதல்

Range இட்டரேட்டரை ஒரு ஜெனரேட்டர் ஃபங்ஷனைப் பயன்படுத்தி மீண்டும் எழுதுவோம்:


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); // வெளியீடு: 1, 2, 3, 4, 5
}

விளக்கம்:

ஜெனரேட்டர் ஃபங்ஷன்கள் next() மெத்தட் மற்றும் done ஃபிளாக்கை தானாகவே கையாள்வதன் மூலம் இட்டரேட்டர் உருவாக்கத்தை எளிதாக்குகின்றன.

உதாரணம்: ஃபைபோனச்சி தொடர் ஜெனரேட்டர் (Fibonacci Sequence Generator)

ஜெனரேட்டர் ஃபங்ஷன்களைப் பயன்படுத்துவதற்கான மற்றொரு சிறந்த உதாரணம் ஃபைபோனச்சி தொடரை உருவாக்குவது:


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

  while (true) {
    yield a;
    [a, b] = [b, a + b]; // ஒரே நேரத்தில் புதுப்பிக்க டிஸ்ட்ரக்சரிங் அசைன்மென்ட்
  }
}

const fibonacci = fibonacciSequence();

for (let i = 0; i < 10; i++) {
  console.log(fibonacci.next().value); // வெளியீடு: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
}

விளக்கம்:

இட்டரேட்டர் புரோட்டோகாலைப் பயன்படுத்துவதன் நன்மைகள்

மேம்பட்ட இட்டரேட்டர் நுட்பங்கள்

இட்டரேட்டர்களை இணைத்தல்

நீங்கள் பல இட்டரேட்டர்களை ஒரே இட்டரேட்டராக இணைக்கலாம். பல மூலங்களிலிருந்து வரும் தரவை ஒரு ஒருங்கிணைந்த வழியில் செயலாக்க வேண்டியிருக்கும் போது இது பயனுள்ளதாக இருக்கும்.


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); // வெளியீடு: 1, 2, 3, a, b, c, X, Y, Z
}

இந்த எடுத்துக்காட்டில், `combineIterators` ஃபங்ஷன் எந்த எண்ணிக்கையிலான இட்டரபிள்களையும் ஆர்குமென்ட்களாக எடுத்துக்கொள்கிறது. இது ஒவ்வொரு இட்டரபிளையும் இட்டரேட் செய்து ஒவ்வொரு ஐட்டத்தையும் யீல்டு (yield) செய்கிறது. இதன் விளைவாக, உள்ளீட்டு இட்டரபிள்களிலிருந்து அனைத்து மதிப்புகளையும் உருவாக்கும் ஒரு ஒற்றை இட்டரேட்டர் கிடைக்கிறது.

இட்டரேட்டர்களை வடிகட்டுதல் மற்றும் மாற்றுதல்

மற்றொரு இட்டரேட்டரால் உருவாக்கப்பட்ட மதிப்புகளை வடிகட்டும் அல்லது மாற்றும் இட்டரேட்டர்களையும் நீங்கள் உருவாக்கலாம். இது தரவை ஒரு பைப்லைனில் செயலாக்க உங்களை அனுமதிக்கிறது, ஒவ்வொரு மதிப்பு உருவாக்கப்படும்போதும் அதற்கு வெவ்வேறு செயல்பாடுகளைப் பயன்படுத்தலாம்.


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); // வெளியீடு: 4, 16, 36
}

இங்கே, `filterIterator` ஒரு இட்டரபிள் மற்றும் ஒரு பிரடிகேட் (predicate) ஃபங்ஷனை எடுத்துக்கொள்கிறது. பிரடிகேட் `true` எனத் திருப்பியளிக்கும் ஐட்டங்களை மட்டுமே அது யீல்டு செய்கிறது. `mapIterator` ஒரு இட்டரபிள் மற்றும் ஒரு டிரான்ஸ்ஃபார்ம் (transform) ஃபங்ஷனை எடுத்துக்கொள்கிறது. இது ஒவ்வொரு ஐட்டத்திற்கும் டிரான்ஸ்ஃபார்ம் ஃபங்ஷனைப் பயன்படுத்தியதன் முடிவை யீல்டு செய்கிறது.

நிஜ-உலக பயன்பாடுகள்

இட்டரேட்டர் புரோட்டோகால் ஜாவாஸ்கிரிப்ட் லைப்ரரிகள் மற்றும் ஃபிரேம்வொர்க்குகளில் பரவலாகப் பயன்படுத்தப்படுகிறது, மேலும் இது பல்வேறு நிஜ-உலக பயன்பாடுகளில், குறிப்பாக பெரிய தரவுத்தொகுப்புகள் அல்லது ασύγχρονη செயல்பாடுகளைக் கையாளும் போது மதிப்புமிக்கது.

சிறந்த நடைமுறைகள்

முடிவுரை

ஜாவாஸ்கிரிப்ட் இட்டரேட்டர் புரோட்டோகால் தரவுக் கட்டமைப்புகளை வரிசையாகப் பெறுவதற்கு ஒரு சக்திவாய்ந்த மற்றும் நெகிழ்வான வழியை வழங்குகிறது. இட்டரபிள் மற்றும் இட்டரேட்டர் புரோட்டோகால்களைப் புரிந்துகொள்வதன் மூலமும், ஜெனரேட்டர் ஃபங்ஷன்களைப் பயன்படுத்துவதன் மூலமும், உங்கள் குறிப்பிட்ட தேவைகளுக்கு ஏற்ப தனிப்பயன் இட்டரேட்டர்களை உருவாக்கலாம். இது தரவுகளுடன் திறமையாக வேலை செய்யவும், குறியீட்டின் வாசிப்புத்திறனை மேம்படுத்தவும், உங்கள் பயன்பாடுகளின் செயல்திறனை அதிகரிக்கவும் உங்களை அனுமதிக்கிறது. இட்டரேட்டர்களில் தேர்ச்சி பெறுவது ஜாவாஸ்கிரிப்டின் திறன்களைப் பற்றிய ஆழமான புரிதலைத் திறக்கிறது மற்றும் மிகவும் நேர்த்தியான மற்றும் திறமையான குறியீட்டை எழுத உங்களுக்கு அதிகாரம் அளிக்கிறது.