ছোট scope-এ বড় কথা !
ছোটবেলায় যখন তুই দুই মাসের বাচ্চা ছিলি, তখন তোর স্কোপ ছিল শুধু খাটের ওপর পর্যন্ত, অর্থাৎ তুই খাটের ওপরেই গড়াগড়ি করতে পারতি। একটু বড় হওয়ার পর তুই শুধু বাসার ভেতরে দৌড়াদৌড়ি করতে পারতি। আবার আরও বড় হয়ে যখন স্কুলে ভর্তি হলি, তখন তোর স্কোপ ছিল স্কুল থেকে বাসা, বাসা থেকে স্কুল। আর যখন কলেজে উঠলি, তখন তুই স্কুল আর বাসার বাইরে প্রাইভেট পড়তে যেতে বা খেলাধুলা করতে পারতি। ফাইনালি ভার্সিটি উঠার পর তোর সামনে দুনিয়া খুলে গেছে। তুই যেখানে খুশি যেতে পারস। মাঝেমধ্যে গ্রুপ স্টাডি আছে বলে বিভিন্ন জায়গায় যেমন, বান্দরবান, সাজেক বা সুন্দরবন ঘুরতে চলে যাস।
অর্থাৎ বয়সের সাথে সাথে তোর স্কোপ বড় হতে শুরু করেছে।
প্রোগ্রামিংয়ের ক্ষেত্রেও স্কোপ নামে কিছু একটা জিনিস আছে এবং এটা সম্পর্কে তোকে কিছুটা জানার দরকার আছে।
1.লোকাল স্কোপ
- ব্লক স্কোপ
- ফাংশন স্কোপ
2.গ্লোবাল স্কোপ
3.Lexical Scope
জাভাস্ক্রিপ্টে বিভিন্ন ধরনের ব্লক আছে। ব্লক বলতে সেকেন্ড ব্র্যাকেট { } দিয়ে সীমাবদ্ধ কোনো কোডকে বুঝায়। নিচে জাভাস্ক্রিপ্টের সমস্ত সম্ভাব্য ব্লকগুলোর উদাহরণ দিলাম—
if (true) {
let message = "This is inside an if block";
console.log(message);
}
Output: This is inside an if blockওপরে if-এর পরে সেকেন্ড ব্র্যাকেটের ভিতরে কিছু কোড আছে। এইটাই একটা ব্লক।
নিচে for লুপের পরে সেকেন্ড ব্র্যাকেটের ভিতরে কিছু কোড আছে। এই সেকেন্ড ব্র্যাকেটের ভিতরের অংশটুকু আরেকটা কোড ব্লক।
for (let i = 0; i < 3; i++) {
let loopMessage = "This is inside a for loop block";
console.log(loopMessage);
}
Output: This is inside a for loop blockwhile লুপ, try-catch বা অন্য সব ক্ষেত্রেও কিন্তু সেকেন্ড ব্র্যাকেট দিয়ে বিভিন্ন ব্লক লেখা হয়।
let count = 0;
while (count < 5) {
console.log(count);
count++;
}এমনকি একটা ফাংশন লিখলে সেকেন্ড ব্র্যাকেটের ভিতরে কিছু কোড থাকে, সেটাও একটা ব্লক। যদিও ফাংশনের এই কোড ব্লককে ফাংশন ব্লক বা অনেক সময় লোকাল স্কোপও বলে ফেলে।
function add(a, b) {
const sum = a + b;
return sum;
}অর্থাৎ যেকোনো দুইটা সেকেন্ড ব্র্যাকেটের ভিতরে এক বা একাধিক লাইনের কোড থাকলে সেটাকে কোড ব্লক বলে।
ব্লক স্কোপ (Block Scope)
একটি কোড ব্লকের ভিতরে অর্থাৎ সেকেন্ড ব্র্যাকেটের ভিতরে যদি let বা const দিয়ে একটা ভেরিয়েবল ডিক্লেয়ার করা হয়, তখন সেটি ব্লক স্কোপে পড়ে। ব্লক স্কোপ বলতে বুঝায় ঐ ভেরিয়েবল শুধু ঐ স্কোপের মধ্যেই এক্সেস করা যাবে। ইউজ করা যাবে। দরকার অনুসারে চেইঞ্জ করা যাবে। তবে ওই ব্লকের বাইরে অর্থাৎ সেকেন্ড ব্র্যাকেটের বাহির থেকে ইউজ করা যাবে না। এক্সেস করা যাবে না। চেইঞ্জ তো করা যাবেই না।
const smart = true;
if (smart) {
let message = "prochur gorom";
console.log("Batas dao");
}
// trying to access outside of the block
console.log(message);
// ReferenceError: message is not definedনোট: let এবং const দিয়ে ডিক্লেয়ার করা ভেরিয়েবলগুলো ব্লক স্কোপের মধ্যেই থাকবে এবং যেখানে ডিক্লেয়ার করা হবে, তার নিচেও ইউজ করা যাবে।
ফাংশন স্কোপ, লোকাল স্কোপ
ধর, আমরা একটা ফাংশন ডিক্লেয়ার করলাম। এই ফাংশনের যে প্যারামিটারগুলোকে (a, b) ফাংশনের ব্র্যাকেটের বাইরে গিয়ে কল করতে চাস বা কোনো কাজে লাগাতে চাস, তখন কিন্তু তুই ইরোর খেয়ে যাবি। নিচের উদাহরণে রান করলে দেখবি একটা ইরোর দেখাচ্ছে। অর্থাৎ ফাংশনের প্যারামিটারগুলো a, b-এর স্কোপ শুধু সেই ফাংশনের ভেতরেই থাকে। এমনকি ফাংশনের ভিতরে যে ভেরিয়েবলগুলো তুই ডিক্লেয়ার করিস, সেটাকেও তুই সেই ফাংশনের বাইরে পাবি না। যেমন, ওপরের ফাংশনের ভিতরে total নামের একটা ভেরিয়েবল ডিক্লেয়ার করা আছে। তুই যদি সেটা বাইরে থেকে কল করতে চাস, তখনও ইরোর খেয়ে যাবি।
function add(a, b) {
const total = a + b;
console.log(a, b);
return total;
}
// trying to access function parameter from outside
console.log(a,b);
add(5, 7);
Output: Uncaught ReferenceError: a is not definedGlobal Scope
তুই যদি ফাংশন কোডের বাইরে বা যেকোনো ব্লকের (যেমন, { }-এর বাইরে) বাইরে ডিক্লেয়ার করিস, তখন সেটা Global Scope-এ থাকে। এই ভেরিয়েবল বা ফাংশনকে পুরো কোডে যেকোনো জায়গায় এক্সেস করা যায়।
let name = "Alex"; // Global Scope
function sayHello() {
console.log("Hello, " + name);
}
sayHello();
Output: Hello, Alexএখানে name গ্লোবাল স্কোপে ডিক্লেয়ার করা হয়েছে, তাই sayHello() ফাংশন থেকে সহজেই এক্সেস করা যাচ্ছে।
Lexical Scope
Lexical Scope হলো স্কোপিংয়ের একটা প্রিন্সিপাল, যেখানে ভেরিয়েবলের এক্সেসিবিলিটি নির্ভর করে কোডের লেখার ধরন এবং অবস্থানের ওপর। ভেতরের স্কোপের কোড বাইরের স্কোপের ভেরিয়েবল এক্সেস করতে পারে, কিন্তু বাইরের স্কোপ থেকে ভেতরের স্কোপের ভেরিয়েবল এক্সেস করা যায় না।
function outerFunction() {
let outerVar = "I'm from outer function";
function innerFunction() {
console.log(outerVar);
}
innerFunction();
}
outerFunction();
Output: I'm from outer functionএখানে innerFunction হচ্ছে outerFunction-এর ভেতরে ডিক্লেয়ার করা একটা ফাংশন, যেটা outerVar-কে এক্সেস করতে পারছে। কারণ, outerVar তার ওপরের স্কোপে আছে।
Scope চেইন
যখন তুই একটা ভেরিয়েবলকে এক্সেস করতে চাইবি, তখন জাভাস্ক্রিপ্ট স্কোপ চেইনের মাধ্যমে খুঁজে দেখে, ওই ভেরিয়েবলটা কোথায় আছে। ভেতরের স্কোপে খুঁজে না পেলে বাইরের স্কোপে খোঁজে, তারপরও না পেলে গ্লোবাল স্কোপে খোঁজে।
let name = "John";
function first() {
let name = "Alex";
function second() {
console.log(name);
}
second();
}
first();
Output: Alexএখানে second ফাংশনের মধ্যে name খুঁজতে গেলে প্রথমে তার ওপরের স্কোপ first-এ খুঁজবে, সেখানে পেয়ে যাওয়ায় গ্লোবাল স্কোপে যাবে না।
সংক্ষেপে
Global Scope – পুরো কোডের যেকোনো জায়গা থেকে এক্সেস করা যায়।
Local Scope – নির্দিষ্ট ফাংশন বা ব্লকের মধ্যে সীমাবদ্ধ।
Lexical Scope – ভেতরের স্কোপ থেকে বাইরের স্কোপের ভেরিয়েবল এক্সেস করতে পারবি। কিন্তু বাইরের স্কোপ থেকে ভিতরের স্কোপের ভেরিয়েবল এক্সেস করতে পারবি না।
স্কোপের এই কনসেপ্ট কিছুটা অ্যাডভান্স কনসেপ্ট, তাই এখন না বুঝলেও টেনশন করিস না।
Practice:
- একটা গ্লোবাল ভেরিয়েবল taxRate ডিক্লেয়ার কর, যার মান হবে 15 । এইখানে taxRate-এর মান বলতে ট্যাক্স রেটের পার্সেন্টেজ বুঝায়। এরপর একটা ফাংশন লিখ, যেটা একজন মানুষের ইনকামকে ইনপুট হিসেবে নিবে। তারপর ফাংশনের ভিতরে taxRate-এর পার্সেন্টেজ ইউজ করে ট্যাক্সের পরিমাণ কত হবে, সেটা রিটার্ন করবে।
- একটা ফাংশন বানা, যেটার মধ্যে let দিয়ে insideSecret নামে ভেরিয়েবল ডিক্লেয়ার কর। এইটার মান হবে “internal secret hiding place” । ফাংশনের বাইরে থেকে insideSecret এক্সেস করতে চেষ্টা কর।
- if ব্লকের ভিতরে let দিয়ে temperature ভেরিয়েবল ডিক্লেয়ার কর এবং সেই ব্লকের বাইরে থেকে এক্সেস করার চেষ্টা কর।
- একটা ফাংশন বানা, যার নাম হবে schoolDetails। এই ফাংশনের ভেতরে schoolName নামে একটা ভেরিয়েবল ডিক্লেয়ার কর। এরপর schoolDetails ফাংশনের ভেতরে আরেকটা nested ফাংশন বানা, যার নাম হবে displaySchoolName। এই nested ফাংশন outer ফাংশনের schoolName ভেরিয়েবল এক্সেস করে সেটা console এ প্রিন্ট করবে। ফাংশনগুলো কল করার সময় যেন আউটপুটে স্কুলের নাম দেখা যায়। এখন বাহির থেকে schoolDetails ফাংশনকে কল কর।