Javascript ES2015 (yoki ES6) da o’zgaruvchi e’lon qilishning ikki yangi yo’li qo’shilgan – const va let. Ushbu maqolada biz var, let va const haqida so’z yuritamiz.
Dastlab mavzuga doir boshqa bilimlarni tushunib olish zarar qilmaydi. Ular o’zgaruvchini e’lon qilish va qiymat berish (declaration vs initialization), scope va hoisting (hosting emas)
Declaration vs Initialization
O’zgaruvchini e’lon qilish quyidagicha bo’ladi.
var declaration
Biz declaration o’zgaruvchi e’lon qildik. Javasciptda o’zgaruvchi e’lon qilinganda unga avtomatik tarzda undefined
qiymati beriladi. Bu degani console.log(declaration)
– undefined
qaytaradi.
Initialization esa o’zgaruvchiga qiymat berish hisoblanadi.
var declaration
console.log(declaration) // undefined
declaration = 'This is an initialization'
Demak biz declaration
o’zgaruvchiga string qiymat berib, uni initsializatsiya qildik.
Scope
Scope dasturda o’zgaruvchi va funksiyalarni qayerda ishlatilishini belgilaydi. Javascriptda ikki turdagi scope bor – global scope va function scope. Agar o’zgaruvchi funksiya ichida e’lon qilinsa, u function scope darajasida ishlaydi, ya’ni funksiya ichida ishlaydi. Funksiyadan tashqarida ishlamaydi.
Quyidagi misolni ko’ramiz.
function getDate () {
var date = new Date()
return date
}
getDate()
console.log(date) // Uncaught ReferenceError: date is not defined
Biz date
o’zgaruvchini getDate()
funksiya ichida e’lon qildik. Uni funksiyadan tashqarida chaqirganimiz uchun, kod «Reference error» qaytaradi. Bu degani date faqat getDate() ichida ishlaydi.
Shuningdek, o’zgaruvchi ichki funksiyalar uchun ham ishlaydi.
function getDate () {
var date = new Date()
function formatDate () {
return date.toDateString().slice(4) // Ishlaydi.
}
return formatDate()
}
getDate()
console.log(date) // Uncaught ReferenceError: date is not defined
getDate()
da e’lon qilingan date
o’zgaruvchisi formatDate()
ichida ham ishlaydi, sababi date
uchun function scope – getDate()
ichida.
Misolni biroz qiyinlashtiramiz. Bizda prices
array bor, biz berilgan discount
qiymatidan foydalanib, chegirmali narxlarni chiqarishimiz kerak bo’lsin. Funksiya tahminan quyidagicha ishlaydi.
discountPrices([100, 200, 300], .5) // [50, 100, 150]
Kod
function discountPrices (prices, discount) {
var discounted = []
for (var i = 0; i < prices.length; i++) {
var discountedPrice = prices[i] * (1 - discount)
var finalPrice = Math.round(discountedPrice * 100) / 100
discounted.push(finalPrice)
}
return discounted
}
Tushunarli kod, menimcha. Lekin bu yerda boshqa til dasturchilari (masalan PHPchilar) e’tibor bermay o’tib ketadigan g’alatilik bor. for
sikl ichidagi o’zgaruvchilar sikldan tashqarida ham ishlayapti. Aslida biz sikl ichidagi e’lon qilgan o’zgaruvchilarimiz – i
, discountedPrice
va finalPrice
yordamchi o’zgaruvchilar edi, to’g’rimi?
Nima uchun ular sikldan tashqarida ham qiymat qaytarishi kerak?
function discountPrices (prices, discount) {
var discounted = []
for (var i = 0; i < prices.length; i++) {
var discountedPrice = prices[i] * (1 - discount)
var finalPrice = Math.round(discountedPrice * 100) / 100
discounted.push(finalPrice)
}
console.log(i) // 3
console.log(discountedPrice) // 150
console.log(finalPrice) // 150
return discounted
}
Ushbu masalaga hoistingni ko’rib chiqib, yana qaytamiz.
Hoisting
Yuqorida, Javasciptda o’zgaruvchi e’lon qilinganda unga avtomatik tarzda undefined
qiymati beriladi, deb aytgan edik. Mana shu avtomatik undefined
berilishining o’zi – hoisting. Yana bir qiziq jihat – o’zgaruvchi e’lon qilinishdan oldin chaqirilsa ham uning qiymati undefined
bo’ladi.
function discountPrices (prices, discount) {
console.log(discounted) // undefined
var discounted = []
for (var i = 0; i < prices.length; i++) {
var discountedPrice = prices[i] * (1 - discount)
var finalPrice = Math.round(discountedPrice * 100) / 100
discounted.push(finalPrice)
}
console.log(i) // 3
console.log(discountedPrice) // 150
console.log(finalPrice) // 150
return discounted
}
Endigina biz asl mavzuga yetib keldik.
var, let va const
Dastlab var
va let
ni solishtiramiz. Asosiy farq – var – function scope, let – block scope. Block scope degani, let e’lon qilingan block ichida ishlaydi. Block deganda {} qavsli operatorlar tushuniladi. Masalan for
sikli yoki if
sharti.
Discount misoliga yana bir marta qaytamiz. Yodingizda bo’lsa, i
, discountedPrice
va finalPrice
yordamchi o’zgaruvchilar sikl tashqarisida ham ishlayotgan edi. Biz ularni faqat block scope – for
ichidagina ishlaydigan qilamiz.
function discountPrices (prices, discount) {
let discounted = []
for (let i = 0; i < prices.length; i++) {
let discountedPrice = prices[i] * (1 - discount)
let finalPrice = Math.round(discountedPrice * 100) / 100
discounted.push(finalPrice)
}
console.log(i)
console.log(discountedPrice)
console.log(finalPrice)
return discounted
}
Funksiyani ishga tushirsak:
discountPrices([100, 200, 300], .5) // ReferenceError: i is not defined
Sababi i
o’zgaruvchi e’lon qilinmagan, ammo u console.log
ichida chaqirilgan. Aniqrog’i i
o’zgaruvchisi – block scope va faqat for
ichidagina amal qiladi. Tashqarida ishlamaydi.
Hoistingda ko’rganimiz – o’zgaruvchi e’lon qilinmay turib, uni chaqirganda undefined
berayotgan edi. Bu to’g’ri ishmas, katta dasturlarda debug qilish, topish qiyin bo’ladigan xatolarni keltirib chiqaradi. Biz var discounted = []
ni let discounted = []
ga o’girganimizda, o’zgaruvchi e’lon qilishdan oldin chaqirish ishlamaydigan bo’ladi.
var va let bo’yicha xulosalar
var
- function scope
- o’zgaruvchi e’lon qilinishidan oldin chaqirilganda
undefined
qaytaradi.
let
- block scope
- o’zgaruvchi e’lon qilinishidan oldin chaqirilganda
ReferenceError
qaytaradi.
let va const
const – let’dagi kabi block scope o’zgaruvchi e’lon qiladi. Yagona farqi – const orqali e’lon qilingan o’zgaruvchiga qayta qiymat bera olmaysiz.
let name = 'John'
const handle = 'worker'
name = 'John Doe' // ok
handle = 'office worker' // TypeError: Assignment to constant variable.
Lekini bor!
const person = {}
person konstant – o’zgarmas qiymatga ega. Lekin konstant obyekt va array e’lon qilib, uni to’ldirish mumkin!
person[firstName] = "John" person[lastName] = "Doe"
O’zgarmasligi shundaki, person
ning o’ziga qiymat berish mumkin emas:
person = { firstName: "John", lastName: "Doe" }
^ Ishlamaydi, sababi person avvalroq const bilan e’lon qilib qo’yilgan. Ishlashi uchun, const’ni let’ga o’zgartirish kerak.
Qaysi birini qachon ishlatish kerak?
- var’dan foydalanmang.
- Ko’p holatda const’dan foydalaning.
- Agar o’zgaruvchining qiymati o’zgaradigan bo’lsa, let’dan foydalaning.
Shu usul xavfsizroq!