Funktsiyalar armiyasi
Quyidagi kod shooters massivini yaratadi.
Har bir funktsiya o’z raqamini chiqarishi kerak. Lekin nimadir noto’g’ri…
function makeArmy() {
let shooters = [];
let i = 0;
while (i < 10) {
let shooter = function() { // shooter funktsiyasini yaratish,
alert( i ); // o'z raqamini ko'rsatishi kerak
};
shooters.push(shooter); // uni massivga qo'shish
i++;
}
// ...va shooterlar massivini qaytarish
return shooters;
}
let army = makeArmy();
// barcha shooterlar o'z raqamlari 0, 1, 2, 3... o'rniga 10 ni ko'rsatadi
army[0](); // 0-raqamli shooterdan 10
army[1](); // 1-raqamli shooterdan 10
army[2](); // 10 ...va hokazo.
Nima uchun barcha shooterlar bir xil qiymatni ko’rsatadi?
Kod mo’ljallangandek ishlashi uchun uni tuzating.
makeArmy ichida aynan nima sodir bo’lishini ko’rib chiqaylik, va yechim aniq bo’lib qoladi.
-
U bo’sh
shootersmassivini yaratadi:let shooters = []; -
Sikl orqali
shooters.push(function)yordamida uni funktsiyalar bilan to’ldiradi.Har bir element funktsiya, shuning uchun natijada olingan massiv shunday ko’rinadi:
shooters = [ function () { alert(i); }, function () { alert(i); }, function () { alert(i); }, function () { alert(i); }, function () { alert(i); }, function () { alert(i); }, function () { alert(i); }, function () { alert(i); }, function () { alert(i); }, function () { alert(i); }, ]; -
Massiv funktsiyadan qaytariladi.
Keyin, keyinroq, istalgan a’zoga chaqiruv, masalan
army[5]()massivdanarmy[5]elementini oladi (bu funktsiya) va uni chaqiradi.Endi nega bunday barcha funktsiyalar bir xil qiymatni, ya’ni
10ni ko’rsatadi?Bu
shooterfunktsiyalari ichida mahalliyio’zgaruvchisi yo’qligi sababli. Bunday funktsiya chaqirilganda, uini o’zining tashqi leksik muhitidan oladi.U holda
ining qiymati nima bo’ladi?Agar manbaga qarasak:
function makeArmy() { ... let i = 0; while (i < 10) { let shooter = function() { // shooter funktsiyasi alert( i ); // o'z raqamini ko'rsatishi kerak }; shooters.push(shooter); // funktsiyani massivga qo'shish i++; } ... }Ko’ramizki, barcha
shooterfunktsiyalarmakeArmy()funktsiyasining leksik muhitida yaratilgan. Lekinarmy[5]()chaqirilganda,makeArmyallaqachon o’z ishini tugatgan vaining oxirgi qiymati10(whilei=10da to’xtaydi).Natijada, barcha
shooterfunktsiyalar tashqi leksik muhitdan bir xil qiymatni oladi va bu oxirgi qiymat, ya’nii=10.Yuqorida ko’rib turganingizdek,
while {...}blokining har bir iteratsiyasida yangi leksik muhit yaratiladi. Shuning uchun, buni tuzatish uchunining qiymatiniwhile {...}bloki ichidagi o’zgaruvchiga nusxalashimiz mumkin:function makeArmy() { let shooters = []; let i = 0; while (i < 10) { let j = i; let shooter = function() { // shooter funktsiyasi alert( j ); // o'z raqamini ko'rsatishi kerak }; shooters.push(shooter); i++; } return shooters; } let army = makeArmy(); // Endi kod to'g'ri ishlaydi army[0](); // 0 army[5](); // 5Bu yerda
let j = i“iteratsiya-mahalliy”jo’zgaruvchisini e’lon qiladi vaini unga nusxalaydi. Primitivlar “qiymat bo’yicha” nusxalanadi, shuning uchun biz aslida joriy sikl iteratsiyasiga tegishliining mustaqil nusxasini olamiz.Shooterlar to’g’ri ishlaydi, chunki
ining qiymati endi bir oz yaqinroq joyda yashaydi.makeArmy()Leksik muhitida emas, balki joriy sikl iteratsiyasiga mos keladigan Leksik muhitda:Agar boshidayoq
forishlatganimizda ham bunday muammoning oldini olish mumkin edi:function makeArmy() { let shooters = []; for(let i = 0; i < 10; i++) { let shooter = function() { // shooter funktsiyasi alert( i ); // o'z raqamini ko'rsatishi kerak }; shooters.push(shooter); } return shooters; } let army = makeArmy(); army[0](); // 0 army[5](); // 5Bu mohiyatan bir xil, chunki
forhar bir iteratsiyada o’ziningio’zgaruvchisi bilan yangi leksik muhit yaratadi. Shuning uchun har bir iteratsiyada yaratilganshooteraynan shu iteratsiyadagi o’zisiga havola qiladi.
Endi, siz buni o’qishga shuncha harakat qilganingizdan so’ng va oxirgi retsept shuncha oddiy – shunchaki for dan foydalaning, siz hayron bo’lishingiz mumkin – bunga arziydimi?
Albatta, agar siz savolga osonlik bilan javob bera olsangiz, yechimni o’qimagan bo’lardingiz. Shuning uchun, umid qilamanki, bu vazifa sizga narsalarni biroz yaxshiroq tushunishga yordam bergan bo’lishi kerak.
Bundan tashqari, haqiqatan ham for dan ko’ra while ni afzal ko’radigan holatlar va bunday muammolar haqiqiy bo’lgan boshqa stsenariylar mavjud.