5-bo‘lim

Funksiyalar

Funksiya e'lon qilish usullari, arrow funksiyalar, parametrlar va standart qiymatlar, ko'lam, hoisting va rekursiya.

🕑 15 daqiqa o‘qish 📄 520 so‘z 👁 1 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Uch xil e'lon usuli
  2. Hoisting - e'lonlarning ko'tarilishi
  3. Parametrlar va standart qiymatlar
  4. Cheksiz argumentlar - rest
  5. Arrow funksiyalar
  6. this va arrow farqi
  7. Ko'lam (scope)
  8. Berkitma (closure)
  9. Rekursiya
  10. Xulosa

Funksiya - nom berilgan kod bo'lagi. Bir marta yozib, xohlagancha chaqirasiz.

Uch xil e'lon usuli #

JavaScript
// 1. Funksiya e'loni (declaration)
function kvadrat(son) {
    return son * son;
}

// 2. Funksiya ifodasi (expression)
const kub = function (son) {
    return son * son * son;
};

// 3. Arrow funksiya
const ikkiBaravar = (son) => son * 2;

console.log("Kvadrat    :", kvadrat(5));
console.log("Kub        :", kub(3));
console.log("Ikki baravar:", ikkiBaravar(7));
Natija
Kvadrat    : 25
Kub        : 27
Ikki baravar: 14

Hoisting - e'lonlarning ko'tarilishi #

JavaScript
// E'lon qilingan funksiyani oldindan chaqirish mumkin
console.log("Oldindan:", oldinChaqirilgan());

function oldinChaqirilgan() {
    return "ishladi";
}

// Ifoda bilan e'lon qilinganini esa mumkin emas
try {
    keyinChaqirilgan();
} catch (xato) {
    console.log("Xato:", xato.constructor.name);
}

const keyinChaqirilgan = function () {
    return "bu ishlamaydi";
};
Natija
Oldindan: ishladi
Xato: ReferenceError
Hoisting: nima ko'tariladi? function e'loni Butunlay ko'tariladi Nomi ham, tanasi ham salom(); // ishlaydi function salom() {} const / let bilan Faqat nomi ko'tariladi Qiymat berilmagan - TDZ salom(); // ReferenceError const salom = () => {}; TDZ = Temporal Dead Zone - e'longacha bo'lgan "o'lik zona"
Chalkashmaslik uchun funksiyani ishlatishdan oldin e'lon qiling

Parametrlar va standart qiymatlar #

JavaScript
function salomlash(ism, salom = "Assalomu alaykum") {
    return `${salom}, ${ism}!`;
}

console.log(salomlash("Husanboy"));
console.log(salomlash("Nodira", "Salom"));

// Standart qiymat oldingi parametrga tayanishi mumkin
function maydon(eni, boyi = eni) {
    return eni * boyi;
}

console.log("Kvadrat  :", maydon(5));
console.log("To'rtburchak:", maydon(5, 3));
Natija
Assalomu alaykum, Husanboy!
Salom, Nodira!
Kvadrat  : 25
To'rtburchak: 15
Standart qiymat faqat undefined da ishlaydi
JavaScript
function sinov(qiymat = "standart") {
    return qiymat;
}

console.log(sinov());              // "standart"
console.log(sinov(undefined));     // "standart"
console.log(sinov(null));          // null  (!)
console.log(sinov(0));             // 0
console.log(sinov(""));            // ""

null - bu aniq berilgan qiymat, shuning uchun standart qiymat ishlamaydi.

Agar null ni ham qamrab olish kerak bo'lsa, ?? ishlating:

JavaScript
function sinov(qiymat) {
    const haqiqiy = qiymat ?? "standart";
    return haqiqiy;
}

Cheksiz argumentlar - rest #

JavaScript
function yigindi(...sonlar) {
    let jami = 0;

    for (const son of sonlar) {
        jami += son;
    }

    return jami;
}

console.log(yigindi(1, 2, 3));
console.log(yigindi(10, 20, 30, 40, 50));
console.log(yigindi());

// Birinchisini alohida olish
function birinchiVaQolgani(birinchi, ...qolgani) {
    return `birinchi: ${birinchi}, qolgani: [${qolgani}]`;
}

console.log(birinchiVaQolgani("a", "b", "c", "d"));
Natija
6
150
0
birinchi: a, qolgani: [b,c,d]

Arrow funksiyalar #

JavaScript
// To'liq shakl
const kvadrat1 = (son) => {
    return son * son;
};

// Bitta ifoda bo'lsa - return va qavslar shart emas
const kvadrat2 = son => son * son;

// Bir nechta parametr - qavs kerak
const qoshish = (a, b) => a + b;

// Parametrsiz - bo'sh qavs
const salom = () => "Salom!";

// Obyekt qaytarish - qavs ichiga olinadi
const yaratish = (ism) => ({ ism: ism, faol: true });

console.log(kvadrat1(4), kvadrat2(4));
console.log(qoshish(3, 7));
console.log(salom());
console.log(yaratish("Aziza"));
Natija
16 16
10
Salom!
{ ism: 'Aziza', faol: true }
Arrow funksiya obyekt qaytarishi
JavaScript
const notogri = () => { ism: "Aziza" };
console.log(notogri());        // undefined

JavaScript { } ni funksiya tanasi deb o'qiydi, obyekt emas. Ichidagi ism: esa yorliq (label) bo'lib qoladi.

To'g'ri yozish - qavs ichiga olish:

JavaScript
const togri = () => ({ ism: "Aziza" });

Qavslar JavaScript ga "bu ifoda, blok emas" deb aytadi.

this va arrow farqi #

JavaScript
const hisoblagich = {
    soni: 0,

    oddiy: function () {
        return this.soni;
    },

    strelka: () => {
        // arrow o'z this ini yaratmaydi
        return typeof this;
    }
};

hisoblagich.soni = 42;

console.log("Oddiy funksiya:", hisoblagich.oddiy());
console.log("Arrow funksiya:", hisoblagich.strelka());
Natija
Oddiy funksiya: 42
Arrow funksiya: object
Obyekt metodini arrow bilan yozmang

Arrow funksiya o'z this iga ega emas - u tashqi ko'lamdan oladi. Obyekt metodi uchun bu deyarli har doim noto'g'ri:

JavaScript
const talaba = {
    ism: "Kamola",
    salom: () => `Men ${this.ism}`      // this.ism - undefined
};

To'g'ri variantlar:

JavaScript
const talaba = {
    ism: "Kamola",
    salom() {                            // qisqa metod sintaksisi
        return `Men ${this.ism}`;
    }
};

Aksincha, callback ichida arrow aynan foydali - u tashqi this ni saqlaydi:

JavaScript
class Taymer {
    constructor() {
        this.soni = 0;
        setInterval(() => this.soni++, 1000);   // this saqlanadi
    }
}

Oddiy function bo'lganda this yo'qolardi va bind(this) yozishga to'g'ri kelardi.

Ko'lam (scope) #

JavaScript
const global = "global";

function tashqi() {
    const tashqiOzgaruvchi = "tashqi";

    function ichki() {
        const ichkiOzgaruvchi = "ichki";
        // uchalasi ham ko'rinadi
        return `${global} > ${tashqiOzgaruvchi} > ${ichkiOzgaruvchi}`;
    }

    return ichki();
}

console.log(tashqi());

// Blok ko'lami
if (true) {
    const blokIchida = "blok";
    console.log("Blok ichida:", blokIchida);
}

try {
    console.log(blokIchida);
} catch (xato) {
    console.log("Blokdan tashqarida:", xato.constructor.name);
}
Natija
global > tashqi > ichki
Blok ichida: blok
Blokdan tashqarida: ReferenceError

Berkitma (closure) #

JavaScript
function hisoblagichYaratish() {
    let soni = 0;              // tashqaridan ko'rinmaydi

    return {
        oshirish() {
            soni++;
            return soni;
        },
        qiymat() {
            return soni;
        }
    };
}

const birinchi = hisoblagichYaratish();
const ikkinchi = hisoblagichYaratish();

birinchi.oshirish();
birinchi.oshirish();
ikkinchi.oshirish();

console.log("Birinchi:", birinchi.qiymat());
console.log("Ikkinchi:", ikkinchi.qiymat());
console.log("To'g'ridan-to'g'ri kirish:", birinchi.soni);
Natija
Birinchi: 2
Ikkinchi: 1
To'g'ridan-to'g'ri kirish: undefined
Berkitma - JavaScript ning eng kuchli imkoniyati

Berkitma (closure) - funksiya o'zi yaratilgan ko'lamni "eslab qolishi".

Yuqoridagi misolda soni o'zgaruvchisi:

  • hisoblagichYaratish tugagandan keyin ham yashaydi;
  • Faqat qaytarilgan metodlar orqali ko'rinadi;
  • Har chaqiruvda yangi nusxasi yaratiladi.

Bu maxfiy holat yaratishning JavaScript dagi klassik usuli - private kalit so'zisiz.

Amaliy qo'llanishlari:

JavaScript
// 1. Bir marta ishlaydigan funksiya
function birMarta(fn) {
    let ishlagan = false;
    return function (...args) {
        if (!ishlagan) {
            ishlagan = true;
            return fn(...args);
        }
    };
}

// 2. Sozlamani "eslab qolish"
function koPaytiruvchi(kopaytma) {
    return (son) => son * kopaytma;
}

const uchGa = koPaytiruvchi(3);

Berkitmalar React hook laridan tortib, modul naqshigacha hamma joyda ishlatiladi.

Rekursiya #

JavaScript
function faktorial(n) {
    if (n <= 1) {
        return 1;              // bazaviy holat - to'xtash sharti
    }
    return n * faktorial(n - 1);
}

console.log("5! =", faktorial(5));

// Ichma-ich obyektni tekislash
function chuqurlik(qiymat) {
    if (!Array.isArray(qiymat)) {
        return 0;
    }

    let eng = 0;
    for (const element of qiymat) {
        eng = Math.max(eng, chuqurlik(element));
    }

    return eng + 1;
}

console.log("Chuqurlik:", chuqurlik([1, [2, [3, [4]]]]));
Natija
5! = 120
Chuqurlik: 4
Bazaviy holatni unutmang

Rekursiv funksiyada to'xtash sharti bo'lmasa, stek to'lib ketadi:

JavaScript
function cheksiz(n) {
    return cheksiz(n - 1);     // to'xtash yo'q
}
Natija
RangeError: Maximum call stack size exceeded

Node.js da stek odatda ~10 000 chaqiruvga yetadi. Bu:

  • Daraxt yoki katalog aylanishi uchun yetarli;
  • 100 000 elementli ro'yxat uchun yetarli emas.

Chuqur rekursiya kerak bo'lsa - siklga aylantiring:

JavaScript
function faktorialSikl(n) {
    let natija = 1;
    for (let i = 2; i <= n; i++) {
        natija *= i;
    }
    return natija;
}

Ba'zi tillar "quyruq rekursiyasi" (tail call) optimizatsiyasini qo'llaydi. JavaScript standartida u bor, lekin brauzerlar deyarli qo'llab-quvvatlamaydi - unga tayanmang.

Amaliy topshiriq
  1. Uch usulda ham funksiya e'lon qiling.
  2. Hoisting farqini function va const bilan sinang.
  3. Standart qiymatli funksiya yozing.
  4. null uzatilganda standart qiymat ishlamasligini ko'rsating.
  5. ...rest bilan cheksiz argument qabul qiling.
  6. Arrow funksiyada obyekt qaytaring - qavsni unutmang.
  7. Obyekt metodini arrow bilan yozib, this muammosini ko'ring.
  8. Berkitma bilan maxfiy hisoblagich yarating.
  9. Ikki hisoblagich bir-biriga ta'sir qilmasligini isbotlang.
  10. Faktorialni rekursiv va siklda yozib taqqoslang.

Xulosa #

  • Funksiya e'loni ko'tariladi (hoisting), ifoda esa yo'q.
  • const bilan e'lon qilingan funksiya TDZ da bo'ladi.
  • Standart qiymat faqat undefined da qo'llanadi, null da emas.
  • ...rest cheksiz argumentni massivga yig'adi.
  • Arrow funksiyada obyekt qaytarish uchun qavs kerak.
  • Arrow o'z this iga ega emas - obyekt metodi uchun yaramaydi.
  • Callback ichida arrow aynan foydali - this saqlanadi.
  • Berkitma funksiyaga o'z ko'lamini eslab qolish imkonini beradi.
  • Har chaqiruvda yangi berkitma yaratiladi.
  • Rekursiyada bazaviy holat bo'lishi shart.
  • Chuqur rekursiya stekni to'ldiradi - siklga aylantiring.

Keyingi bo'limda massivlar bilan ishlashni boshlaymiz.

Xatolik topdingizmi?

Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.