JavaScript Destructuring, Spread, Rest & ES6 Modules (ఆధునిక క్లీన్ కోడ్)
పాత కాలపు JavaScript లో ఒక ఆబ్జెక్ట్ లేదా అర్రే నుండి వివరాలు తీసుకోవాలంటే const name = user.name; const age = user.age; const role = user.role; అని పదే పదే బోరింగ్ కోడ్ రాయాల్సి వచ్చేది. ES6 (Modern JS) ఈ శ్రమను తొలగించి, ప్రపంచవ్యాప్తంగా డెవలపర్ల కోడింగ్ వేగాన్ని 3 రెట్లు పెంచే అద్భుతమైన టూల్స్ని అందించింది.
లగేజ్ సూట్కేస్ అనాలజీ (The Luggage Suitcase Analogy):
1. Destructuring (సూట్కేస్ అన్ప్యాకింగ్): ప్రయాణంలో మీ బ్యాగ్ (Object / Array) లో బట్టలు, కెమెరా, పాస్పోర్ట్ అన్నీ కలిసి ఉంటాయి. అవసరమైనప్పుడు బ్యాగ్ మొత్తాన్ని మోయకుండా, కావాల్సిన కెమెరాను మాత్రమే ఒక్క సెకనులో బయటకు తీయడమే Destructuring: const { camera } = luggage;
2. Spread Operator ... (విప్పదీసి కలపడం): ఒక పూసల దండలోని పూసలన్నింటినీ విప్పదీసి కొత్త దండలో కలపడం. (ఒరిజినల్ డేటాను తాకకుండా క్లోన్ చేయడానికి).
3. Rest Parameter ... (మిగిలినవన్నీ బుట్టలో వేయడం): ఫంక్షన్కు మొదటి 2 ప్రధాన వస్తువులు ఇచ్చి, మిగిలిన ఎన్ని వచ్చినా వాటన్నింటినీ ఒకే అర్రేగా మూటగట్టడం.
ఈ పాఠంలో మీరు రేపు React Props లేదా Node.js APIs లో నిత్యం వాడే సింటాక్స్లతో పాటు, పెద్ద పెద్ద ప్రాజెక్టులను చిన్న చిన్న ఫైల్స్గా విడదీసే ES6 Modules (import & export) ఆర్కిటెక్చర్ను సంక్షిప్త కోడ్తో నేర్చుకుందాం.
ఒక కాంప్లెక్స్ డేటా స్ట్రక్చర్ నుండి మనకు కావాల్సిన ప్రాపర్టీలను ఒకే ఒక్క లైన్లో వేరియబుల్స్గా మార్చుకోవచ్చు:
| ఫీచర్ | Array Destructuring [a, b] |
Object Destructuring { x, y } |
|---|---|---|
| ఎంపిక ఆధారం | వరుస క్రమం (Order / Position) ముఖ్యం. | కీ పేరు (Key Name) సరిపోవాలి (క్రమంతో సంబంధం లేదు). |
| పేరు మార్చడం (Renaming) | మనకు నచ్చిన ఏ పేరైనా పెట్టుకోవచ్చు [first, second]. |
కోలన్ వాడాలి: { originalKey: newName }. |
| డిఫాల్ట్ విలువలు | విలువ లేకపోతే: [a = 10, b = 20]. |
కీ లేకపోతే: { city = "హైదరాబాద్" }. |
జావాస్క్రిప్ట్ లో ... ని చూసినప్పుడు చాలామంది అయోమయానికి గురవుతారు. ఎందుకంటే ఇది పరిస్థితిని బట్టి రెండు వ్యతిరేక పనులు చేస్తుంది:
🎭 మూడు చుక్కల (...) యొక్క రెండు ముఖాలు:
• 1. Spread Operator (విస్తరించడం / Unpacking):
ఇది ఒక అరే లేదా ఆబ్జెక్ట్ లోపల ఉన్న ఎలిమెంట్లను విప్పదీసి బయటకు చల్లుతుంది!
const nums = [1, 2, 3]; const copy = [...nums, 4]; // [1, 2, 3, 4]
• 2. Rest Parameter (మూటగట్టడం / Packing):
ఫంక్షన్ పారామీటర్లలో వాడినప్పుడు, మిగిలిపోయిన అన్ని విడివిడి ఆర్గ్యుమెంట్లను పట్టుకుని ఒకే ఒక్క అరేగా మూటగడుతుంది!
function sum(...numbers) { /* numbers అనేది అరే */ }
ఒక వెబ్సైట్ కోడ్ వేల లైన్లు పెరిగినప్పుడు, వాటన్నింటినీ ఒకే ఫైల్ లో రాస్తే మెయింటెనెన్స్ అసాధ్యం. ES6 మోడ్యూల్స్ మన కోడ్ను స్వతంత్ర లెగో బ్లాక్స్ (Lego Blocks) లాగా మారుస్తాయి:
🧱 Named Export vs Default Export:
• Named Export (ఒకటి కంటే ఎక్కువ టూల్స్): ఒక ఫైల్ నుండి ఎన్ని ఫంక్షన్లనైనా ఎగుమతి చేయవచ్చు.
export const add = (a, b) => a + b;
దిగుమతి చేసుకునేటప్పుడు అవే పేర్లతో కర్లీ బ్రాకెట్లలో తీసుకోవాలి: import { add } from './math.js';
• Default Export (ఫైల్ కి ఒక్కటే మెయిన్ బాస్): ఆ ఫైల్ లోని ప్రధాన ఫంక్షన్/క్లాస్ కోసం.
export default class User {}
దిగుమతి చేసుకునేటప్పుడు బ్రాకెట్లు అవసరం లేదు: import User from './user.js';
Object destructuring, Array destructuring with Rest, మరియు Spread ക്లోన్ లన్నింటినీ ప్రదర్శించే కేవలం 15 లైన్ల కాంపాక్ట్ కోడ్:
const user = { name: "విక్రమ్", role: "Dev", salary: 90000 };
// 1. Object Destructuring: పేరు మార్చడం (alias) & డిఫాల్ట్ విలువ
const { name: userName, role, city = "హైదరాబాద్" } = user;
// 2. Array Destructuring & Rest Parameter (మిగిలినవి అరేగా)
const [first, second, ...remaining] = [10, 20, 30, 40, 50];
// 3. Spread Operator: పాత డేటా మారకుండా క్లోన్ చేసి కొత్త విలువ కలపడం
const updatedUser = { ...user, role: "Lead Dev", active: true };
console.log("యూజర్ వివరాలు:", userName, role, city);
console.log("అర్రే ముక్కలు:", first, second, remaining);
console.log("అప్డేటెడ్ ఆబ్జెక్ట్:", updatedUser.role, "| Active:", updatedUser.active);
యూజర్ వివరాలు: విక్రమ్ Dev హైదరాబాద్
అర్రే ముక్కలు: 10 20 [ 30, 40, 50 ]
అప్డేటెడ్ ఆబ్జెక్ట్: Lead Dev | Active: true
name: userNameద్వారా ఒరిజినల్ కీnameని మనకు నచ్చినuserNameవేరియబుల్గా మార్చుకున్నాం.{ ...user, role: "Lead Dev" }లోroleమాత్రమే ఓవర్రైట్ అయింది; మిగిలిన ప్రాపర్టీలు అలాగే క్లోన్ అయ్యాయి.
ఆధునిక జావాస్క్రిప్ట్ లో ఎక్కువగా జరిగే పొరపాట్లు:
const { name } = undefined; // ❌ TypeError: Cannot destructure property 'name' of undefined!
పరిష్కారం: డిఫాల్ట్ ఖాళీ ఆబ్జెక్ట్ ఇవ్వాలి: const { name } = user || {};
Spread ఆపరేటర్ కేవలం మొదటి స్థాయిని మాత్రమే కాపీ చేస్తుంది (Shallow Copy). లోపల ఉన్న Nested ఆబ్జెక్టుల మెమరీ రిఫరెన్స్ అలాగే ఉంటుంది! డీప్ కాపీ కోసం structuredClone() వాడాలి.
function test(a, ...rest, b) {} // ❌ SyntaxError: Rest parameter must be last!
Rest ఎల్లప్పుడూ ఆఖరి పారామీటర్గా మాత్రమే ఉండాలి.
బ్రౌజర్లో import/export వాడేటప్పుడు HTML స్క్రిప్ట్ ట్యాగ్లో <script type="module" src="app.js"></script> అని రాయకపోతే ఎర్రర్ వస్తుంది.
{ name: myName = 'Guest' } లో కోలన్ : అంటే పేరు మార్చడం, = అంటే డిఫాల్ట్ విలువ ఇవ్వడం. రెండింటినీ కలిపి వాడేటప్పుడు గందరగోళ పడకూడదు.
రియాక్ట్ లేదా మోడరన్ ఈ-కామర్స్ యాప్స్ లో వాడే అసలైన ఇమ్యూటబుల్ కార్ట్ స్టేట్ అప్డేటర్ లాజిక్ (కేవలం 15 లైన్లలో):
ఈ కోడ్ను కంపైలర్ లో రన్ చేసి ఒరిజినల్ కార్ట్ చెక్కుచెదరకుండా కొత్త కార్ట్ ఎలా తయారైందో గమనించండి:
// Spread మరియు Rest ఉపయోగించి స్టేట్ అప్డేట్ చేసే స్వచ్ఛమైన ఫంక్షన్
function updateCart(prevCart, newItem, ...discountCodes) {
const hasDiscount = discountCodes.includes("SAVE20");
const discountRate = hasDiscount ? 0.2 : 0;
return {
...prevCart, // పాత ప్రాపర్టీలు క్లోన్
items: [...prevCart.items, newItem], // కొత్త ఐటమ్ సురక్షితంగా చేర్చడం
totalDiscount: prevCart.totalDiscount + newItem.price * discountRate,
appliedCodes: [...prevCart.appliedCodes, ...discountCodes]
};
}
const originalCart = { items: [{ name: "కీబోర్డ్", price: 1000 }], totalDiscount: 0, appliedCodes: [] };
// కొత్త ఐటమ్ మరియు కూపన్ కోడ్స్ తో అప్డేట్
const nextCart = updateCart(originalCart, { name: "మౌస్", price: 500 }, "WELCOME", "SAVE20");
console.log("కొత్త కార్ట్ మొత్తం ఐటమ్స్:", nextCart.items.length);
console.log("లభించిన డిస్కౌంట్:", nextCart.totalDiscount);
console.log("అసలు కార్ట్ భద్రంగా ఉందా?:", originalCart.items.length === 1); // true!
కొత్త కార్ట్ మొత్తం ఐటమ్స్: 2
లభించిన డిస్కౌంట్: 100
అసలు కార్ట్ భద్రంగా ఉందా?: true
ఈ క్రింది ప్రశ్నలకు స్వయంగా సమాధానం ఆలోచించి, డ్రాప్డౌన్ తెరిచి పరిశీలించండి:
- రెండు వేరియబుల్స్ విలువలను తాత్కాలిక వేరియబుల్ (temp) లేకుండా Destructuring ద్వారా ఎలా మార్పిడి (Swap) చేయవచ్చు?
- Spread Operator
...ని ఆబ్జెక్టులపై వాడినప్పుడు డీప్ కాపీ ఎందుకు జరగదు? - ఒక ఫంక్షన్లో Rest Parameter తర్వాత సాధారణ పారామీటర్ను ఎందుకు పెట్టకూడదు?
- Named Export మరియు Default Export మధ్య గల ప్రధాన తేడా ఏమిటి?
const [first, , third] = [1, 2, 3];లో కామా ఖాళీగా వదిలేస్తే ఏమి జరుగుతుంది?- ఆధునిక ఫ్రేమ్వర్క్స్ (React / Vue) లో Immutability ఎందుకు చాలా కీలకం?
👉 సమాధానాలు మరియు వివరణలు చూడండి (Click to Expand)
1. సమాధానం: [a, b] = [b, a]; ద్వారా కేవలం ఒక్క లైన్లో స్వాప్ చేయవచ్చు.
2. సమాధానం: Spread కేవలం మొదటి స్థాయి ప్రైమిటివ్ విలువలను మాత్రమే కాపీ చేస్తుంది; నెస్టెడ్ ఆబ్జెక్టుల మెమరీ అడ్రస్ అలాగే షేర్ అవుతుంది (Shallow Copy).
3. సమాధానం: Rest అనేది 'మిగిలిన అన్నింటినీ' పట్టుకోవాలి. దాని తర్వాత మరొకటి ఉంటే ఏది మిగిలిందో బ్రౌజర్ నిర్ణయించలేదు, కాబట్టి SyntaxError వస్తుంది.
4. సమాధానం: Named Export లో ఎన్ని ఫంక్షన్లయినా ఎగుమతి చేయవచ్చు (కర్లీ బ్రాకెట్లతో ఇంపోర్ట్ చేయాలి). Default Export ఒక ఫైల్ కి ఒక్కటే ఉంటుంది (బ్రాకెట్లు లేకుండా ఇంపోర్ట్ చేసుకోవచ్చు).
5. సమాధానం: రెండో ఎలిమెంట్ (2) స్కిప్ చేయబడి, third లోకి నేరుగా 3 వెళుతుంది.
6. సమాధానం: ఒరిజినల్ స్టేట్ని మార్చకుండా కొత్త స్టేట్ తయారు చేయడం వల్ల మెమరీ రిఫరెన్స్ మారి, UI త్వరగా రీ-రెండర్ అవుతుంది మరియు అన్డు/రీడూ హిస్టరీ సులభం అవుతుంది.
📌 సారాంశం (Quick Summary):
- Destructuring: డేటా నుండి అవసరమైన వాటిని ఒక్క లైన్ లో వెలికితీయడం.
- Spread
...: ఎలిమెంట్లను విప్పదీసి క్లోన్ చేయడానికి మరియు కలపడానికి వాడతారు. - Rest
...: మిగిలిన అన్ని ఆర్గ్యుమెంట్లను ఒకే అరేగా ప్యాక్ చేయడానికి వాడతారు. - ES6 Modules:
exportమరియుimportద్వారా కోడ్ను శుభ్రమైన ఫైల్స్గా విడదీయడం. - బెస్ట్ ప్రాక్టీస్: స్టేట్ ని నేరుగా మార్చకుండా ఎల్లప్పుడూ Spread తో కాపీ చేసి అప్డేట్ చేయండి.
👉 తర్వాతి పాఠం: Asynchronous JavaScript (Promises & async/await) →
వెబ్ డెవలప్మెంట్లో అత్యంత శక్తివంతమైన కాన్సెప్ట్ లోకి అడుగుపెడుతున్నాం! సర్వర్ నుండి API డేటాను తెచ్చేటప్పుడు బ్రౌజర్ ఫ్రీజ్ అవ్వకుండా బ్యాక్గ్రౌండ్లో పనులు ఎలా జరగాలి?
తర్వాతి అధ్యాయంలో Callbacks, Promises, async/await మరియు Fetch API గురించి వివరంగా నేర్చుకుందాం!