Nima uchun mutatsiyalar sodir bo’ladi? Primitive va reference qiymatlar

Javascriptda o’zgaruvchi e’lon qilinganda unga ikki turdagi qiymatdan biri beriladi – primitive va reference qiymatlar. Agar qiymat numberstringbooleanundefinednull, or symbol tiplardan biri bo’lsa, u primitive qiymat; object, array, functionreference qiymat hisoblanadi.

const age = 28 // primitive
const name = 'John' // primitive
const loading = false // primitive
const user = undefined // primitive
const response = null // primitive
const counter = Symbol('counter') // primitive

const user = { name: 'John' } // reference
const friends = ['Johnny', 'Bravo'] // reference
const doThing = () => ({}) // reference

Ko’rinishidan primitive va reference qiymatlar bir xil bo’lsada, aslida qiymat berish turlicha ishlaydi. Asosiy farq – ularning xotirada qanday joylashuvida ko’rinadi. Primitive’da qiymat xotirada to’g’ridan to’gri saqlanadi. Reference tipdagi qiymat esa xotirada bog’langan (referenced) manzil ko’rinishida joy egallaydi. Tushunarliroq bo’lishi uchun ba’zi misollarni ko’rib chiqamiz.

let surname = 'Doe'
let displayName = surname

surname = 'Bravo'

console.log(surname) // 'Bravo'
console.log(displayName) // 'Doe'

G’ayritabiiy hech narsa sodir bo’lmadi.

Yana bir misolni ko’rib chiqamiz. Bunda o’zgaruvchiga reference qiymat beramiz.

let leo = {
  type: 'Dog',
  name: 'Leo'
}

let snoop = leo

snoop.name = 'Snoop'

console.log(leo.name) // Snoop
console.log(snoop.name) // Snoop

Dastlab, leo o’zgaruvchini e’lon qilib, unga object qiymat berdik. Xotirada object qiymat uchun reference manzil qo’shildi. Keyin snoop o’zgaruvchiga leo o’zgaruvchini berdik, bunda snoop o’zgaruvchi xotirada leo o’zgaruvchiga bog’lab qo’yildi. snoop.name ni o’zgartirganimizda, leo.name ham o’zgardi. Sababi o’zgaruvchiga reference qiymat berilganda unga xotirada reference manzil qo’shiladi. Bizning holatda leo va snoop xotirada bir xil manzilga ega. Shuning uchun, bir object’ning property’sini (name) o’zgartirganimizda, ikkinchi o’zgaruvchiga ham ta’sir qildi. Buning nomini mutatsiya (mutation) deyiladi.

Reference qiymatlarga yana bir misol:

const name = 'Tyler'
const friend = 'Tyler'
name === friend // true

const leo = { type: 'Dog', name: 'Leo' }
const moa = { type: 'Dog', name: 'Leo' }
leo === moa // false

Ikki primitive qiymat bir-biriga teng, ammo ikki reference qiymat bir biriga teng emas, zo’ra?! Sababi ham o’sha, reference qiymat xotirada reference manzil egallagani uchun. Bizning holatda leo va moa ikki turli manzilga ega, shu sababli ular teng emas.

Xulosa

primitive qiymatlar mutatsiyaga uchramaydi (immutable). Ularni o’zgaruvchilarga berish, bir o’zgaruvchi qiymatini boshqasiga berish mumkin. Reference qiymatlarda esa ehtiyot bo’lish kerak. Chunki mutatsiya faqat qiymat berishda emas, hatto funksiya argumentini o’zgartirishda ham ro’y berishi mumkin.