Function declaration, function expression va strelka funksiya bir-biridan nimasi bilan farq qiladi?
Savol
Funksiya e'loni (function declaration), funksional ifoda (function expression) va strelka funksiya o'rtasidagi farq nimada — ayniqsa hoisting va this kontekstida?
Qisqa javob
Function declaration to'liq ko'tariladi (hoisting) va e'lon qilingan qatorgacha ham mavjud bo'ladi. Function expression faqat o'zgaruvchi sifatida ko'tariladi (qiymatsiz) yoki const/let orqali e'lon qilingan bo'lsa, umuman ko'tarilmaydi. Ikkalasi ham o'z this va argumentsiga ega. Strelka funksiya chaqiriladigan funksiya sifatida ko'tarilmaydi, o'z this, arguments va superiga ega emas — ularni tashqi ko'rinish sohasidan oladi.
Batafsil javob
Function declaration — function foo() {}. Dvigatel bunday e'lonlarni kod qator-qator bajarilishidan oldin, ko'rinish sohasini yaratish bosqichida qayta ishlaydi, shuning uchun funksiyani kodda uning e'lonidan yuqorida chaqirish mumkin.
Function expression — o'zgaruvchiga o'zlashtirilgan funksiya: const foo = function() {} (anonim yoki nomlangan bo'lishi mumkin). Bu yerda faqat o'zgaruvchi ko'tariladi (var foo → undefined, let/const foo → temporal dead zone), lekin funksiyaning o'zi qiymat sifatida ko'tarilmaydi. Uni o'zlashtirish qatoridan oldin chaqirib bo'lmaydi.
Strelka funksiya — const foo = () => {} — bu har doim ifoda (expression), hech qachon e'lon (declaration) emas. Asosiy farq hoisting'da emas, xatti-harakatda:
- O'z
thisiga ega emas — uni leksik jihatdan, yaratilgan paytdagi o'rab turuvchi koddan oladi. - O'z
argumentsobyektiga ega emas — murojaat qilinganda tashqi funksiyaningargumentsi olinadi (yoki u bo'lmasa xato). - Konstruktor sifatida ishlatib bo'lmaydi (
new (() => {})()TypeErrortashlaydi). prototypega ega emas.thisni o'zgartirish uchunbind/call/applyorqali bog'lab bo'lmaydi.
Amaliy qoida: oddiy funksiyalarni (function) obyekt metodlari uchun va dinamik this kerak bo'lgan joylarda ishlatish kerak (masalan, DOM elementlaridagi hodisa ishlovchilarida, bu yerda this elementning o'zi bo'lishi kerak). Strelka funksiyalarni — tashqi kontekstning thisini saqlab qolish kerak bo'lgan callback'lar uchun (masalan, klass metodlari yoki React komponentlari ichida).
Strelka funksiyalardagi this xatti-harakatining batafsil tahlili — alohida mavzu, bu yerda faqat shu muhim: strelka funksiya o'z kontekstini yaratmaydi, balki tashqisini "shaffof" ravishda ishlatadi.
Misol
// Hoisting: declaration e'lon qilinguncha ham ishlaydi
console.log(sum(2, 3)) // 5 — ishlaydi
function sum(a, b) {
return a + b
}
// Function expression: o'zlashtirilguncha TDZ / undefined
console.log(typeof multiply) // "undefined" (var) — o'zgaruvchi ko'tarilgan, qiymati yo'q
var multiply = function (a, b) {
return a * b
}
// console.log(divide()) // ReferenceError: Cannot access 'divide' before initialization
const divide = (a, b) => a / b
// Oddiy funksiyaning o'z this'i vs strelkaning leksik this'i
const counter = {
value: 0,
incRegular: function () {
setTimeout(function () {
// bu yerdagi this — counter emas (qat'iy rejimda undefined)
console.log(this === counter) // false
}, 0)
},
incArrow: function () {
setTimeout(() => {
// strelka this'ni incArrow'dan oladi, u yerda esa this === counter
console.log(this === counter) // true
}, 0)
},
}
counter.incRegular()
counter.incArrow()
// arguments: oddiy funksiyada bor, strelkada yo'q
function regular() {
return arguments.length
}
console.log(regular(1, 2, 3)) // 3
const arrow = (...args) => args.length // strelka arguments'ni shunday taqlid qiladi
console.log(arrow(1, 2, 3)) // 3
Qo'shimcha savollar
- Nega strelka funksiyani
newbilan konstruktor sifatida ishlatib bo'lmaydi? - Temporal dead zone nima va u
let/consthoisting'i bilan qanday bog'liq? - Strelka funksiya sifatida e'lon qilingan obyekt metodi
thisning kutilgan xatti-harakatini qanday buzadi?