JavaScript Arrays: Advanced (অ্যারে)
Mutating বনাম non-mutating, shallow/deep copy, value vs reference, method chaining, common pitfalls, interview notes — বাংলায়।
অ্যারের এই ধাপে কীভাবে, কখন কী বদলায় — সেই গভীর ধারণা। এগুলোই interview-এ ও বড় project-এ দরকারি সূক্ষ্ম বিষয়।
Value বনাম Reference
let x = 10;
let y = x;
y = 20;
console.log(x); // 10 (value copy — স্বাধীন)
const a = [1, 2];
const b = a; // reference — একই array-এর দিকে তাকায়
b.push(3);
console.log(a); // [1, 2, 3] — a-ও বদলে গেল!
console.log(a === b); // truePrimitive (number, string, boolean) value দিয়ে যায়; array ও object reference দিয়ে যায়। তাই const তৈরি করা array-এর element বদলানো যায় — const মানে reference পরিবর্তন করা নয়।
Mutating বনাম Non-mutating
const nums = [3, 1, 2];
// Mutating (মূল বদলায়)
nums.sort();
console.log(nums); // [1, 2, 3]
// Non-mutating (নতুন দেয়)
const copy = [3, 1, 2].toSorted();
console.log(copy); // [1, 2, 3]
console.log([3, 1, 2]); // [3, 1, 2]| Mutating (মূল বদলায়) | Non-mutating (নতুন array) |
|---|---|
| push, pop, unshift, shift | concat, slice, map, filter |
| sort, reverse, splice | toSorted, toReversed, toSpliced |
| fill, copyWithin | spread [...arr] |
আধুনিক JS-এ toSorted(), toReversed(), toSpliced() মেথড মূল না বদলে নতুন array দেয় — এটা বেশি নিরাপদ। sort() ব্যবহার করলেই আগে [...arr].sort() দিয়ে copy নিন।
Shallow বনাম Deep copy
const nested = [[1, 2], [3, 4]];
// Shallow copy — উপরের স্তর আলাদা, ভেতরের array একই reference
const shallow = [...nested];
shallow[0].push(99);
console.log(nested); // [[1, 2, 99], [3, 4]] — নিচের স্তরও বদলে গেল!
// Deep copy — পুরোটা আলাদা
const deep = structuredClone(nested);
deep[0].push(42);
console.log(nested); // [[1, 2], [3, 4]] — অপরিবর্তিত[...arr] বা slice() শুধু shallow copy — এক-স্তরের অ্যারে হলে যথেষ্ট; nested array/object হলে structuredClone() দিন (সম্পূর্ণ deep copy)।
Method chaining
const products = [
{ name: "মোবাইল", price: 15000, stock: 3 },
{ name: "ল্যাপটপ", price: 65000, stock: 0 },
{ name: "হেডফোন", price: 2000, stock: 10 },
];
const total = products
.filter(p => p.stock > 0) // stock আছে যাদের
.map(p => p.price) // শুধু দাম
.reduce((sum, price) => sum + price, 0);
console.log(total); // 17000প্রতিটি মেথড একটা নতুন array/মান দেয়, তাই তার উপর পরের মেথড চালানো যায়। তবে মনে রাখবেন: non-mutating মেথড দিয়ে চেইন করুন — না হলে ধাপে ধাপে মূল ডেটা নষ্ট হয়ে যাবে।
সাধারণ ভুল (pitfalls)
// ১. sort() string হিসেবে সাজায়
const wrong = [10, 2, 1].sort();
console.log(wrong); // [1, 10, 2] ❌
// ২. find বনাম filter গুলিয়ে ফেলা
// find প্রথম মিল দেয়; filter সব মিল দেয়
// ৩. empty array-তে find/filter — result আসে
console.log([].find(() => true)); // undefined
// ৪. reduce-এ initial value ভুলে যাওয়া
console.log([1, 2, 3].reduce((a, b) => a + b)); // 6 (চলে)
console.log([].reduce((a, b) => a + b)); // TypeError ❌
console.log([].reduce((a, b) => a + b, 0)); // 0 ✓reduce()-এ initial value `0` দেওয়া সবচেয়ে নিরাপদ — খালি array-তে crash হয় না। আর সংখ্যা sort-এ সবসময় comparator (x, y) => x - y দিন।
Interview notes
Interview-এ যেসব প্রশ্ন প্রায়শই আসে, সাথে সাথে উত্তর —
// Q: duplicate value বাদ দেওয়ার সহজ উপায়?
const arr = [1, 2, 2, 3, 3, 3];
console.log([...new Set(arr)]); // [1, 2, 3]
// Q: মোট যোগফল?
console.log([1, 2, 3].reduce((a, b) => a + b)); // 6
// Q: সর্বোচ্চ মান?
console.log(Math.max(...[10, 20, 5])); // 20
// Q: শর্তে দুটি array-এর সাধারণ মান?
const shared = [1, 2, 3].filter(x => [2, 3, 4].includes(x));
console.log(shared); // [2, 3]
// Q: array খালি কিনা?
console.log([].length === 0); // trueconst temp = myArray; করলে temp-এ পরিবর্তন আসল array-ও বদলায়। অনুলিপি দরকার হলে সবসময় [...myArray] অথবা structuredClone(myArray) ব্যবহার করুন।
সব element ঘুরে কিছু করতে for...of, সূচকসহ জটিল ব্রেক-শর্তে for, রূপান্তর/filter/aggregate-এ মান map/filter/reduce। functional মেথড সাধারণত বেশি পরিষ্কার ও bug-মুক্ত।