Scope in JavaScript
Primitive and Reference types Value
Primitive
প্রিমিটিভ এর বাংলা অর্থ হলো আদিম
। জাভাস্ক্রিপ্টে যেসব DATATYPE আছে যেমনঃ
- String
- Number
- Boolean
- Null
- Undefined
এইগুলো হলো জাভাস্ক্রিপ্টের মূল বা একক। এগুলো ব্যাবহার করে অন্যান্য ডাটা বানানো হয়। এগুলোকে বলা হয় প্রিমিটিভ ডাটা বা ভ্যালু ।
References
জাভাস্ক্রিপ্টের Array
এবং Object
কে বলা হয় রেফারেন্স টাইপ ডাটা বা ভ্যালু ।
প্রিমিটিভ এবং রেফারেন্স টাইপ ডাটার পার্থক্যঃ
প্রিমিটিভ এবং রেফারেন্স টাইপ ডাটার মধ্যে মূল যেই পার্থক্য রয়েছে তা হলো এর ডাটার বিহেবিয়ার নিয়ে। যেমন নিচে উদাহরণের মাধ্যমে বুঝানো হলোঃ
Primitive
প্রিমিটিভ ডাটা শুধুমাত্র ভ্যালুটা শেয়ার করে। ডাটার রেফারেন্স শেয়ার করেনা।
Reference
এখানে a
কে যখন b
দ্বারা রি-এসাইন করা হয়েছে তখন স্বাভাবিক ভাবেই আ এর ভ্যালু চেঞ্জ হয়ে b
এর যেই ভ্যালু ছিল তা হয়ে গিয়েছে। কিন্তু নিচে যখন b
এর ভ্যালু চেঞ্জ করা হয়েছে সেই চেঞ্জটা a
তেও এসে প্রভাব ফেলেছে এবং a
সহ চেঞ্জ হয়ে গেছে। কারণ এখানে a
তে যখন b
এসাইন করা হয়েছিল তখন a
তে b
এর রেফারেন্স সহ চলে গেছিল,তাই যেকোন একটা কে চেঞ্জ করলেই দুইটাই চেঞ্জ হয়ে যাচ্ছে।
এখানে যেই বিষয়টা হয়েছে তা হলোঃ
a
আর b
যখন ডিফাইন করা হয়েছে তখন মেমরিতে দুইটা Array
এলোকেটেড করা হয়েছে এবং Array
দুটি তাদের যেই Variables
এর নাম a
এবং b
তার দিয়ে পয়েন্ট করে আছে। কিন্তু যখন a = b
করা হয়েছে তখন দুইটা পয়েন্টার এক হয়ে b
এর ভ্যালু থেকে a
আর b
এর দিকে পয়েন্ট হয়ে গেছে। তাই এখন a
অথবা b
যেইটাই চেঞ্জ করা হউক না কেন তা দুইটাকেই চেঞ্জ করবে।
এটাই হলো primitives
আর References
ভ্যালুর মধ্যে মূল পার্থক্য ।
Shallow Copy Vs Deep Copy
জাভাস্ক্রিপ্টে "শ্যালো কপি" (Shallow Copy) এবং "ডিপ কপি" (Deep Copy) হল দুটি আলাদা প্রক্রিয়া যেগুলো ব্যবহার করে একটি Object
বা Array
'র কপি তৈরি করা হয়। তবে এদের মধ্যে বড় পার্থক্য হচ্ছে কিভাবে ডেটা কপি করা হয়। নিচে প্রতিটি কনসেপ্ট বিস্তারিতভাবে ব্যাখ্যা করছি:
শ্যালো কপি (Shallow Copy)
শ্যালো কপিতে কেবলমাত্র অবজেক্টের প্রথম লেভেলের ভ্যালুগুলি কপি করা হয়। এর মানে হলো, যদি অবজেক্ট বা আরে'র মধ্যে নেস্টেড অবজেক্ট থাকে, তাহলে সেগুলি রেফারেন্স হিসেবে কপি হয়। অর্থাৎ, নেস্টেড অবজেক্ট বা আরে'র জন্য একটি রেফারেন্স তৈরি হয়, নতুন অবজেক্টে একই ডেটা শেয়ার করে।
উদাহরণ:
let originalArray = [1, 2, { a: 3, b: 4 }];
// শ্যালো কপি তৈরি করা
let shallowCopy = [...originalArray];
console.log(shallowCopy); // [1, 2, { a: 3, b: 4 }]
// নেস্টেড অবজেক্ট পরিবর্তন করা
shallowCopy[2].a = 10;
console.log(originalArray); // [1, 2, { a: 10, b: 4 }]
console.log(shallowCopy); // [1, 2, { a: 10, b: 4 }] // নেস্টেড অবজেক্ট রেফারেন্স একারে কপি হওয়ার কারনে কপি ডাটাতে চেঞ্জ করলেও তা মেইন ডাটাকেও চেঞ্জ করে দিয়েছে।
এই উদাহরণে দেখা যাচ্ছে যে, originalArray
এবং shallowCopy
একই নেস্টেড অবজেক্ট শেয়ার করছে। যখন shallowCopy[2].a
পরিবর্তন করা হয়, তখন মূল অবজেক্টেও পরিবর্তন ঘটে। এটি শ্যালো কপির একটি সীমাবদ্ধতা।
শ্যালো কপি তৈরি করার পদ্ধতি:
- Spread Operator:
let copy = [...array];
ডিপ কপি (Deep Copy)
ডিপ কপিতে একটি অবজেক্টের প্রতিটি লেভেলের কপি তৈরি করা হয়, এমনকি নেস্টেড অবজেক্টেরও আলাদা কপি করা হয়। এর ফলে মূল অবজেক্টের কোনো পরিবর্তন নতুন কপি অবজেক্টকে প্রভাবিত করে না এবং বিপরীতও ঘটে না।
উদাহরণ:
let originalArray = [1, 2, { a: 3, b: 4 }];
// ডিপ কপি তৈরি করা (JSON পদ্ধতি ব্যবহার করে)
let deepCopy = JSON.parse(JSON.stringify(originalArray));
console.log(deepCopy); // [1, 2, { a: 3, b: 4 }]
// নেস্টেড অবজেক্ট পরিবর্তন করা
deepCopy[2].a = 10;
console.log(originalArray); // [1, 2, { a: 3, b: 4 }]
console.log(deepCopy); // [1, 2, { a: 10, b: 4 }]
এখানে দেখা যাচ্ছে যে, deepCopy[2].a
পরিবর্তন করার পরেও originalArray
এর নেস্টেড অবজেক্ট অপরিবর্তিত রয়েছে। কারণ, ডিপ কপিতে নেস্টেড অবজেক্টের নতুন কপি তৈরি হয়।
ডিপ কপি তৈরি করার পদ্ধতি:
-
JSON.parse(JSON.stringify(obj))
: সহজ পদ্ধতি, তবে ফাংশন ও undefined হ্যান্ডেল করতে পারে না।
-
- Lodash লাইব্রেরির cloneDeep মেথড Lodash একটি জনপ্রিয় জাভাস্ক্রিপ্ট লাইব্রেরি, যা অনেক ধরনের ইউটিলিটি ফাংশন সরবরাহ করে। cloneDeep হল একটি বিশেষ মেথড যা ডিপ কপি তৈরি করতে পারে।
উদাহরণ:
প্রথমে lodash ইনস্টল করতে হবে:
npm i --save lodash
তারপর
const _ = require("lodash");
let originalObject = { a: 1, b: { c: 2, d: 3 } };
let deepCopiedObject = _.cloneDeep(originalObject);
deepCopiedObject.b.c = 10;
console.log(originalObject); // { a: 1, b: { c: 2, d: 3 } }
console.log(deepCopiedObject); // { a: 1, b: { c: 10, d: 3 } }
Lodash এর cloneDeep মেথড সমস্ত ডেটা টাইপ এবং নেস্টেড অবজেক্ট সঠিকভাবে হ্যান্ডেল করতে পারে। এটি ফাংশন, তারিখ, Map, Set এবং অন্যান্য জটিল ডেটা স্ট্রাকচার হ্যান্ডেল করার ক্ষেত্রে খুবই কার্যকর।
শ্যালো কপি বনাম ডিপ কপি পার্থক্য:
শ্যালো কপি | ডিপ কপি |
---|---|
শুধুমাত্র প্রথম লেভেলের কপি করে। | প্রতিটি লেভেলের জন্য নতুন কপি তৈরি করে। |
নেস্টেড অবজেক্টগুলো রেফারেন্স হিসেবে কপি হয়। | নেস্টেড অবজেক্টগুলোর সম্পূর্ণ নতুন কপি হয়। |
এই দুই ধরনের কপির মধ্যে পার্থক্য নির্ভর করে আপনার প্রয়োজনের উপর।
Advanced JavaScript
this
এর ব্যাবহার। কোথায় এবং কিভাবে ।
Implicit Binding
👉রুলসঃ
দেখতে হবে যে,ফাংশন কল হয়েছে কোথায়, যেখানে কল হয়েছে তার সামনে কি কোন ডট আছে কিনা,যদি থাকে তাহলে তার সামনে কি আছে। যদি কিছু থাকে তাহলে সেটাই হলো this
। এক্ষেত্রে এক্সেপ্সন হলো this
শুধু নরমাল ফাংশনেই কাজ করবে। কিন্তু Arrow
ফাংশন this
বলে কিছু চিনবেনা।
উদাহরণঃ
let player = {
name: "Mashrafe",
age: 38,
printPlayerName: function () {
console.log(this.name); // এখানে this দিয়ে `player` অবজেক্টটাকে পয়েন্ট করা হয়েছে।
},
};
player.printPlayerName();
Explicitly Binding
.call()
👉 কখনও কখনও বাহিরের কোন ফাংশনকে অন্য কোন অবজেক্ট দিয়ে কল করার প্রয়োজন হয় । সেক্ষেত্রে সিনট্যাক্স হয় এরকমঃ
function printName() {
// এটা একটা গ্লোবাল ফাংশন
console.log(this.name);
}
let player = {
name: "Sakib",
age: 33,
};
printName.call(player); // এই গ্লোবাল ফাংশনটাকে `player` অবজেক্ট দিয়ে `.call()` করা হয়েছে ।
এক্ষেত্রে .call()
এর ভিতরে যা পাস করা হয়, this
সেটাকেই পয়েন্ট করে। এক্ষেত্রে explicitly বলে দেয়া হচ্ছে যে this
কি হবে ।
.apply()
👉 .apply()
আর .call()
একই কাজ করে। সবকিছুই সেম। তবে.apply()
তার second parameter এ Array
নিতে পারে । যেকানে .call()
Array
নিতে পারেনা।
function printPlayerName() {
console.log(`${this.name} is ${vertue} `);
}
let mashrafe = {
name: "Mashrafe",
age: 36,
};
let vartu1 = "Honest";
let vartu2 = "Captain";
let vartu3 = "Leader";
let vertue = [vartu1, vartu2, vartu3];
printPlayerName.apply(mashrafe, vertue);
.bind()
👉 .bind()
ও .call()
এর মতোই সেম কাজ করে। তবে পার্থক্য হলো .bind()
ফাংশনটিকে সরাসরি কল না করে দিয়ে ফাংশনের একটা নতুন ইন্সটেন্স রিটার্ন করে। এবং সেই ইন্সটেন্সকে যেই ভেরিয়েবলে রাখা হয় সেই ভেরিয়েবল দ্বারা কল করতে হয়।
উদাহরনঃ
function printAPlayerName() {
console.log(this.name);
}
let bdPlayer = {
name: "Ashraful",
age: 39,
};
let printFunction = printAPlayerName.bind(bdPlayer);
printFunction();
JS Itarator
Itarables
কি ?
Itarables
বলতে মূলত সেই সমস্ত জিনিস বা অবজেক্ট কে বোঝায়,যেগুলোর মধ্যে দিয়ে লুপ eg: for...of
করে স্টেপ বাই স্টেপ যাওয়া যায়। যেমনঃ Array
,String
,Map
,Set
টেকনিক্যালি বললে, যেসব অবজেক্টের প্রোটোটাইপের ভিতরে symbol.itarator
প্রপার্টি রয়েছে সেটাই itarable
symbol.itarator
এর মাধ্যমেই জাভাস্ক্রিপ্ট ডিফাইন করে যে, কোনটা itarable
আর কোনটা নয় ।
Map
,Set
বলতে এখানে জাভাস্ক্রিপ্ট এর Map
Set
ডাটা স্ট্রাকচার কে
বুঝানো হয়েছে
itarator বলতে কি বুঝায় ?
itarable
অবজেক্টকে যার দ্বারা itarate
করা যায়,সেটাই হলো itarator
itarating
বলতে কি বুঝায় ?
itarating
বলতে মূলত Itarables
অবজেক্টগুলোকে লুপ করে স্টেপ বাই স্টেপ যাওয়ার যেই প্রসেস সেটাকে বুঝায় । যখন itarate
করা হয় তখন সেটা হলো itarating
Array
কে itarate
করা ।
const arr = [1, 2, 3, 4, 5, 6, 7];
for (item of arr) {
console.log(item);
}
//Output: 1 2 3 4 5 6 7
String
কে itarate
করা ।
const str = "Bangladesh";
for (character of str) {
console.log(character);
}
// Output : B a n g l a d e s h
Asyncronus JavaScript
জাভাস্ক্রিপ্ট হলো সিঙ্গেল থ্রেডেড প্রোগ্রামিং ল্যাঙ্গুয়েজ