--- title: জাভাস্ক্রিপ্টে ডেটা স্ট্রাকচার slug: Web/JavaScript/Data_structures tags: - JavaScript translation_of: Web/JavaScript/Data_structures ---
সব প্রোগ্রামিং ল্যাংগুয়েজের নিজস্ব ডেটা স্ট্রাকচার থাকে (যা ব্যবহার করে আপনি আপনার ডেটা বা তথ্য প্রোগ্রামে রাখতে পারেন) - তবে একেক প্রোগ্রামিং ভাষায় একেক রকম ডেটা স্ট্রাকচার দেখা যায়। এই আর্টিকেলে জাভাস্ক্রিপ্টের নিজস্ব ডেটা স্ট্রাকচার আর সেগুলোর বিভিন্ন প্রোপার্টি (বৈশিষ্ট্য) নিয়ে আলোচনা করা হয়েছে। এই নিজস্ব ডেটা স্ট্রাকচার গুলো ব্যবহার করে অন্যান্য ডেটা স্ট্রাকচার বানানো যাবে। যেখানে সম্ভব অন্য ভাষার সাথে পার্থক্য ও দেখানো হয়েছে।
JavaScript একটি loosely typed বা dynamic ভাষা। যার মানে হচ্ছে আমাদের আগে থেকে কোন variable এর type বলে দিতে বা ঠিক করে দিতে হবে না। কোন প্রোগ্রাম চলাকালে অটোমেটিক এর type ঠিক হয়ে যায়। যার মানে দাঁড়ায়, আমরা একই নামের বিভিন্ন type এর variable তৈরি করতে পারি!!
var foo = 42; // foo is now a Number
var foo = 'bar'; // foo is now a String
var foo = true; // foo is now a Boolean
ECMAScript স্ট্যান্ডার্ড অনুযায়ী ৭ ধরণের ডেটা স্ট্রাকচার আছেঃ
নিচের আলোচনায় আমরা দেখব কিভাবে এগুলো ব্যবহার করে ডেটা রাখা যায় আর কীভাবে এগুলোর সাহায্যে আরও উন্নতমানের ডেটা স্ট্রাকচার তৈরি করা যায়।
অবজেক্ট ছাড়া বাকি সব টাইপের ডেটার মান তৈরি করার পর আর পরিবর্তন করা যায় না। বিশেষকরে, স্ট্রিং (যেখানে C ভাষায় স্ট্রিং এর মান পরিবর্তন করা যায়)। এই টাইপের ডেটাকে আমরা মৌলিক (primitive) টাইপের বলে থাকি। নিচে {{ anch("Strings") }} নিয়ে আলোচনায় এই বিষয়ে বিস্তারিত রয়েছে।
শুধুমাত্র চারটি ধ্রুবক (কন্সট্যান্ট) দিয়েই এই ডেটাটাইপ গুলো প্রকাশ করা সম্ভবঃ বুলিয়ান প্রকাশ করার জন্য true
, false
, নাল প্রকাশের জন্য null
, আর অসংজ্ঞায়িত প্রকাশের জন্য undefined
। যেহেতু এগুলো কন্সট্যান্ট, এগুলো উঁচুমানের ডেটা রাখতে পারে না।
ECMAScript স্ট্যান্ডার্ড অনুযায়ী সংখ্যা প্রকাশ করার জন্য একটি মাত্র নাম্বার-টাইপ আছেঃ "double-precision 64-bit binary format IEEE 754 value"। অন্যান্য প্রোগ্রামিং ভাষার মত Integer (পূর্ণ সংখ্যা) প্রকাশ করার জন্য আলাদা কোন টাইপ নেই! ভগ্নাংশ রাখার পাশাপাশি জাভাস্ক্রিপ্টের এই একমাত্র নাম্বার টাইপ দিয়ে +Infinity
, -Infinity
, এবং NaN
(not-a-number) এই বিশেষ প্রতীক গুলোও প্রকাশ করা যায়।
যদিও একটি সংখ্যা সাধারণত শুধুমাত্র এর মানই প্রকাশ করে, জাভাস্ক্রিপ্টের কিছু বাইনারী অপারেটর আছে, যেগুলো দিয়ে বিট মাস্কিং পদ্ধতিতে একটি মাত্র সংখ্যা থেকেই অনেকগুলো বুলিয়ান মান প্রকাশ করা সম্ভব। তবে এরকম ব্যবহার নিরুৎসাহিত করা হয়, কারণ জাভাস্ক্রিপ্টে অন্য পদ্ধতিতে বুলিয়ান মান রাখা যায় (যেমন বুলিয়ান মানের array ব্যবহার করে অথবা অবজেক্টে প্রত্যেকটা বুলিয়ান মানের জন্য একটা করে প্রোপার্টি ব্যবহার করে)। বিট মাসস্কিং ব্যবহার করলে কোড দুর্বোধ্য হয়, পরে এই কোড নিয়ে আর কাজ করাও যায় না। ক্ষেত্র বিশেষে বিট মাসস্কিং ব্যবহার না করে কোন উপায় থাকে না, যেমন স্টোরেজ সীমাবদ্ধতা থাকলে অথবা নেটওয়ার্ক দিয়ে প্রত্যেক্টা বিট পাঠানোর সময়। তবে যখনই পারা যায়, বিট মাসস্কিং শেষ সম্বল হিসেব রেখে দিয়ে দেখতে হবে অন্য কোন উপায়ে কোডটা করে ফেলা যায় কিনা!
স্ট্রিং হচ্ছে "বাক্য" বা একসাথে অনেকগুলো অক্ষর। C ভাষার সাথে জাভাস্ক্রিপ্টের পার্থক্য হচ্ছে জাভাস্ক্রিপ্টের স্ট্রিং তৈরি করার পর পরিবর্তন করা যায় না। তবে একটি স্ট্রিং এর ওপর কোন অপারেশন প্রয়োগ করে নতুন অন্য স্ট্রিং তৈরি করা যায়। যেমনঃ
String.substr()
।String.concat()
ফাংশন ব্যবহার করে।জটিল রকমের ডেটাকে স্ট্রিং দিয়ে প্রকাশ করার প্রবণতা খুবই লক্ষ্য করা যায়। কারণ, কিছু সুবিধা পাওয়া যায় প্রায় সবকিছু স্ট্রিং দিয়ে প্রকাশ করতে গেলেঃ
responseText ব্যবহার করা হচ্ছে
, ইত্যাদি।) তাই মনে হতে পারে সব ডেটাই তো স্ট্রিং দিয়ে প্রকাশ করা যাচ্ছে!এটা সত্য যে প্রায় সব ডেটা স্ট্রাকচার কেই স্ট্রিং দিয়ে প্রকাশ করা সম্ভব, কিন্তু এটা ভাল আইডিয়া না। যেমন, আলাদা করার জন্য কিছু একটা ব্যবহার করে কেউ স্ট্রিং দিয়ে লিস্ট তৈরি করার চেষ্টা করতে পারে (যেখানে array বেশি উপযুক্ত হত)। এখন আলাদা করার জন্য যেই অক্ষরটা ব্যবহার করা হয়েছে, সেটিই যদি লিস্টের সদস্য হিসেবে হাজির হয় তাহলে সমস্যা দেখা দিবে। কোন এসকেপ অক্ষর ব্যবহার করা যেতে পারে হয়ত, কিন্তু এত কাহিনী কীর্তি করার তো দরকার নেই কারণ লিস্ট রাখার জন্য নিবেদিত ডেটা স্ট্রাকচার ই আছে, যেটা ব্যবহার না করে স্ট্রিং ব্যবহার করলে অপ্রয়োজনীয় বোঝা বহন করতে হবে।
তাই শুধুমাত্র টেক্সট-জাতীয় ডেটা রাখার জন্যই স্ট্রিং ব্যবহার করা উচিত। জটিল ডেটা রাখার জন্য স্ট্রিংটিকে পার্স করে উপযুক্ত ডেটা স্ট্রেকচার ব্যবহার করতে হবে।
জাভাস্ক্রিপ্টে, অবজেক্টকে আমরা অনেকগুলো ডেটা রাখার জন্য একটা প্যাকেট হিসেবে চিন্তা করতে পারি। অবজেক্ট লিটেরেল সিনট্যাক্স ব্যবহার করে আমরা অবজেক্টের অল্প কিছু প্রোপার্টির মান দিয়ে দিতে পারি। তবে পরে যেকোন সময় যেকোন প্রোপার্টি ঐ অবজেক্টে যোগ বা বিয়োগ করা যাবে। যেকোন টাইপের ডেটা আমরা প্রোপার্টি হিসেবে রাখতে পারি অবজেক্টের, অন্য অবজেক্টের ডেটাও। এভাবে, জটিল ডেটা স্ট্রাকচার তৈরি করা সম্ভব।
জাভাস্ক্রিপ্টে অবজেক্ট হচ্ছে key-value ম্যাপিং। মানে অবজেক্টের কোন একটা স্ট্রিং key এর মান হিসেবে যেকোন ডেটা টাইপের value রাখা যাবে। তাই অবজেক্ট কে হ্যাশ-ম্যাপের বিকল্প হিসেবে ব্যবহার করা যায়। তবে, নন-স্ট্যান্ডার্ড __proto__
pseudo প্রোপার্টি সাবধানে ব্যবহার করতে হবে। যেখানে প্রযোজ্য, সেখানে __proto__
এর ভুল মান বসালে অবজেক্টের নিজস্ব প্রোটোটাইপ (ধরণ) বদলে যাবে। যেসব ক্ষেত্রে আমরা জানি না কোন স্ট্রিং এর উৎস কী (যেমন কোন ইনপুট ফিল্ড) সেসব ক্ষেত্রে সাবধান থাকতে হবেঃ অন্যরা এই সমস্যায় ভুগেছে। এসব ক্ষেত্রে কোন StringMap abstraction ব্যবহার করা যেতে পারে।
ফাংশনও অবজেক্ট, জাভাস্ক্রিপ্টে। পার্থক্য হল, ফাংশন কে কল করা যায়।
Arrays ও অবজেক্ট, জাভাস্ক্রিপ্টে। তবে এখানে, প্রোপার্টি গুলোর key হচ্ছে পূর্ণ সংখ্যা আর বিশেষ 'length' প্রোপার্টি রয়েছে এদের। আরও কাহিনী হল, এরেগুলো ইনহেরিট হয় Array.prototype
থেকে - যার ফলে বেশ কিছু দরকারি ফাংশন পাওয়া যায় এরে অবজেক্ট গুলো থেকে। যেমন, indexOf
ফাংশন ব্যবহার করে array তে কোন একটা মান (সদস্য) আছে কিনা জানা যায় আবার push
ফাংশন ব্যবহার করে এরে এর শেষে কোন সদস্য যোগ করা যায়। লিস্ট কিংবা সেট হিসেবে ব্যবহার করার জন্য তাই এরে হচ্ছে সবচেয়ে উপযুক্ত ডেটা-স্ট্রাকচার।
তারিখ প্রকাশ করার জন্য সবচেয়ে উপযুক্ত হবে নিজস্ব Date
ইউটিলিটি ব্যবহার করা।
স্ট্যান্ডার্ড নয়। আশা করা যায় ECMAScript 6. ভার্সনে স্ট্যান্ডার্ড হবে।
এসব ডেটা স্ট্রাকচার কোন অবজেক্টের রেফারেন্স কে key হিসেবে নিতে পারে। সেট দিয়ে একসারি (set) অব্জেট প্রকাশ করা হয়, আবার WeakMaps আর ম্যাপ দিয়ে কোন অবজেক্ট কে ভ্যালু হিসেবে রাখা হয়। ম্যাপ আর উইকম্যাপ এর মাঝে পার্থক্য হচ্ছেঃ ম্যাপে অবজেক্ট key, enumerate করা যায়। আর উইকম্যাপে গার্বেজ-কালেকশন বেশি ভালভাবে কাজ করে।
শুধুমাত্র ECMAScript 5 ব্যবহার করেই ম্যাপ ও সেট ইমপ্লিমেন্ট করা সম্ভব। কিন্তু যেহেতু অবজেক্ট compare (যেমন, কোনটা কার থেকে ছোট সেই তুলনা করতে গেলে) করা সম্ভব না, লুক-আপ পারফরমেন্স linear হয়ে যাবে এতে। এর থেকে নেটিভ ইমপ্লেমেন্টেশন ভাল হবে কারণ তাহলে লুক-আপ পারফরমেন্স লগারিদমিক থেকে কন্সটান্ট পর্যন্ত হতে পারবে।
সাধারণভাবে, DOM নোডে ডেটা bind করার জন্য যে কেউ সরাসরিভাবে অবজেক্টে প্রোপার্টি হিসেবে দিয়ে দিতে পারে, অথবা data-*
attribute গুলো ব্যবহার করতে পারে। এর সমস্যা হল একই context এ চলছে এরকম যেকোন স্ক্রিপ্ট এই ডেটা ব্যবহার করতে পারবে। ম্যাপ আর উইকম্যাপ দিয়ে ডেটা কোন অব্জেক্টের সাথে সহজেই প্রাইভেট ভাবে bind করা যায়।
স্ট্যান্ডার্ড নয়। আশা করা যায় ECMAScript 6. ভার্সনে স্ট্যান্ডার্ড হবে।