మీరు ఒక బగ్‌ను మూడు ఫైళ్ల ద్వారా వెతికినప్పుడు, ఒక హానిలేని హెల్పర్ ఫంక్షన్ యూజర్ పేరును మార్చేసిందని తెలుస్తుంది. మీరు అసలు డేటాను ముట్టుకోలేదు. లేదా మీరు అలా అనుకున్నారు. JavaScriptలో, ఒక వేరియబుల్‌ను మరొక దానికి అసైన్ చేయడం అంటే మీరు అనుకున్నది ఎప్పుడూ జరగదు. ఈ భాష తన డేటాను రెండు స్టోరేజ్ వ్యూహాలుగా (storage strategies) విభజిస్తుంది, మరియు మీరు దేనిని ఉపయోగిస్తున్నారో మర్చిపోవడం వల్ల ప్రొడక్షన్ కోడ్‌లోకి సైలెంట్ మ్యుటేషన్లు (silent mutations) ప్రవేశిస్తాయి.

దీనిని నివారించడానికి, ఇంజిన్ చూసే విధంగానే ప్రిమిటివ్ వాల్యూస్ (primitive values) మరియు ఆబ్జెక్ట్‌ల (objects) మధ్య తేడాను మీరు ఖచ్చితంగా అర్థం చేసుకోవాలి.

Primitives: అసలైన కాపీలు

ప్రిమిటివ్ అనేది ఒకే ఒక, విడదీయలేని డేటా (datum). దీనిని చిన్న JavaScript వాల్యూస్‌గా విభజించలేము. ఈ భాష ఏడు ప్రిమిటివ్ రకాలను నిర్వచిస్తుంది: String, Number, Boolean, Undefined, Null, Symbol, మరియు BigInt.

ప్రిమిటివ్‌లు అటామిక్ (atomic) కాబట్టి, అవి సాధారణంగా నేరుగా వేరియబుల్ బైండింగ్‌లోనే ఉంటాయి. మీరు ఒక ప్రిమిటివ్ వేరియబుల్‌ను మరొక దానికి కాపీ చేసినప్పుడు, ఇంజిన్ అసలైన డేటాను డూప్లికేట్ చేస్తుంది. ప్రతి వేరియబుల్ మెమరీలో దాని స్వంత స్వతంత్ర స్లాట్‌ను పొందుతుంది.

let a = "Alina";
let b = a;
b = "Ali";

console.log(a); // "Alina"
console.log(b); // "Ali"

ఇక్కడ, a మార్పు లేకుండా ఉంటుంది. bని రీఅసైన్ చేయడం వల్ల ఒక కొత్త వాల్యూ సృష్టించబడింది మరియు b దానిని సూచిస్తుంది, అయితే a ఇంకా దాని అసలు స్ట్రింగ్‌నే కలిగి ఉంటుంది. ఈ ప్రవర్తనను 'copy by value' అంటారు. ఇది నంబర్లు, బూలియన్స్, సింబల్స్ మరియు మిగిలిన ప్రిమిటివ్ రకాలకు కూడా ఒకేలా పనిచేస్తుంది. మీరు వాటిని ఫంక్షన్లలోకి పంపవచ్చు, రీఅసైన్ చేయవచ్చు లేదా ఇతర వేరియబుల్స్‌పై సైడ్ ఎఫెక్ట్స్ (side effects) గురించి ఆందోళన చెందకుండా తిరిగి పంపవచ్చు (return చేయవచ్చు).

Objects: షేర్డ్ అడ్రస్‌లు

ఆబ్జెక్ట్‌లు భిన్నమైనవి. ఆబ్జెక్ట్ అనేది బహుళ డేటా భాగాలను కలిపి ఉంచే ఒక కాంపోజిట్ కంటైనర్. ఈ కేటగిరీలో ప్లెయిన్ ఆబ్జెక్ట్‌లు, అర్రేలు (arrays), ఫంక్షన్లు, డేట్స్ మరియు ఇతర అన్ని నాన్-ప్రిమిటివ్ రకాలు ఉంటాయి. ఈ స్ట్రక్చర్‌లు పెద్దవిగా మరియు నెస్టెడ్ (nested) గా ఉండటం వల్ల, JavaScript మొత్తం ఆబ్జెక్ట్‌ను వేరియబుల్ లోపల నిల్వ చేయదు. బదులుగా, వేరియబుల్ ఒక రిఫరెన్స్‌ను (reference) కలిగి ఉంటుంది, ఇది ప్రాథమికంగా వేరే చోట నిల్వ చేయబడిన అసలు డేటాను సూచించే మెమరీ అడ్రస్.

మీరు ఒక ఆబ్జెక్ట్‌ను కొత్త వేరియబుల్‌కు అసైన్ చేసినప్పుడు, ఇంజిన్ అడ్రస్‌ను మాత్రమే కాపీ చేస్తుంది, ఆబ్జెక్ట్‌ను కాదు. ఇప్పుడు రెండు వేరియబుల్స్ ఖచ్చితంగా ఒకే ఇంటిని సూచిస్తాయి.

const user = { name: "Alina" };
const copy = user;
copy.name = "Ali";

console.log(user.name); // "Ali"

copy.nameని మార్చడం వల్ల user.name కూడా మారిపోయింది, ఎందుకంటే రెండు పేర్లు ఒకే అండర్‌లైయింగ్ ఆబ్జెక్ట్‌ను సూచిస్తాయి. దీనినే 'copy by reference' అంటారు. అర్రేల విషయంలో కూడా ఇదే విధమైన ఆశ్చర్యకరమైన విషయం కనిపిస్తుంది:

const scores = [82, 91, 74];
const backup = scores;
backup.push(88);

console.log(scores); // [82, 91, 74, 88]

మెమరీలో ఒకే ఒక అర్రే ఉంది. scores మరియు backup అనేవి కేవలం దానిని సూచించే రెండు గుర్తులు మాత్రమే.

const కీవర్డ్ గందరగోళాన్ని మరింత పెంచుతుంది. constతో ఒక ఆబ్జెక్ట్‌ను డిక్లేర్ చేయడం వల్ల వేరియబుల్ బైండింగ్ లాక్ చేయబడుతుంది, తద్వారా మీరు దానిని కొత్త అడ్రస్‌కు పాయింట్ చేయలేరు. కానీ ఇది ఆబ్జెక్ట్‌ను లాక్ చేయదు.

const settings = { theme: "dark" };
settings.theme = "light";        // Works perfectly.
settings = { theme: "dark" };    // TypeError

డెవలపర్లు తరచుగా const అనేది ఇమ్మ్యూటబిలిటీని (immutability) ఇస్తుందని ఆశిస్తారు. కానీ అది అలా కాదు. ఇది కేవలం రిఫరెన్స్‌ను రీఅసైన్ చేయడాన్ని మాత్రమే నిరోధిస్తుంది. మీరు కంటెంట్‌ను మార్చకుండా ఉండాలనుకుంటే, మీరు ఉద్దేశపూర్వకంగా కాపీ చేయాలి.

అసలైన బగ్‌లు ఎక్కడ ఉంటాయి

రిఫరెన్స్ బగ్‌లు అరుదుగా స్పష్టమైన వేరియబుల్ రీఅసైన్‌మెంట్‌లుగా కనిపిస్తాయి. అవి ఫంక్షన్ కాల్స్ (function calls) లోపల దాగి ఉంటాయి.

function addTimestamp(record) {
  record.timestamp = Date.now();
  return record;
}

const original = { id: 1 };
addTimestamp(original);

console.log(original.timestamp); // A number now exists here. Oops.

record అనే పారామీటర్ రిఫరెన్స్ యొక్క కాపీని స్వీకరించింది. ఫంక్షన్ లోపల ఏదైనా ప్రాపర్టీ మ్యుటేషన్ (property mutation) జరిగితే, అది నేరుగా కాల్ చేసిన (caller) ఆబ్జెక్ట్‌లోకి రాయబడింది. ఆ ఫంక్షన్ ఒక సాధారణ ట్రాన్స్‌ఫర్మేషన్ (transformation) లాగా కనిపించినప్పటికీ, అది స్కోప్ బౌండరీల (scope boundaries) మధ్య స్టేట్‌ను లీక్ చేసింది.

ఈ ప్యాటర్న్ React వంటి UI ఫ్రేమ్‌వర్క్‌లలో చాలా ఇబ్బందికరంగా ఉంటుంది, అక్కడ స్టేట్ అప్‌డేట్‌లు (state updates) ఆధారపడి ఉంటాయి