Javascriptda var, let va const

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?

  1. var’dan foydalanmang.
  2. Ko’p holatda const’dan foydalaning.
  3. Agar o’zgaruvchining qiymati o’zgaradigan bo’lsa, let’dan foydalaning.

Shu usul xavfsizroq!

const let var