জাভাস্ক্রিপ্ট ডেটা স্ট্রাকচার - অবজেক্ট
Tags: javascript, programming, object, bangla
Published: 2023-04-11 17:31:14

সোর্স: www.learnersbucket.com

## অবজেক্ট কি?
অবজেক্ট হলো কতগুলো প্রোপার্টির একটি বক্স যেটি মিউটেবল। যেখানে প্রোপার্টি গুলো `key-value` জোড়ায় থাকে। `key` যেকোন স্ট্রিং বা এমটি স্ট্রিং হতে পারে এবং ভেলু জাভাস্ক্রিপ্ট-এ বিদ্যমান যেকোন টাইপের ডেটা হতে পারে, কিন্তু `undefined` হতে পারবে না। প্রত্যেকটি `key` তে `value` এড করা বাধ্যতামূলক।
`number`, `string`, `boolean`, `null` এবং `undefined` বাদে জাভাস্ক্রিপ্ট-এ সবকিছুই অবজেক্ট। `number`, `string`, `boolean` অবজেক্ট-এর মতোই, যেহেতু এদের অবজেক্ট-এর মতো মেথড রয়েছে, কিন্তু এরা ইমমিউটএবল।
### জাভাস্ক্রিপ্ট-এ অবজেক্ট-এর লিস্ট

- Dates
- Regular Expression
- Maths
- Arrays
- Function
- Objects
- Booleans (যখন `new` কিওয়ার্ড দিয়ে কনস্ট্রাক্টর হিসেবে কল করা হয়)
- Strings (যখন `new` কিওয়ার্ড দিয়ে কনস্ট্রাক্টর হিসেবে কল করা হয়)
- Numbers (যখন `new` কিওয়ার্ড দিয়ে কনস্ট্রাক্টর হিসেবে কল করা হয়)

## জাভাস্ক্রিপ্ট-এ অবজেক্ট ডিকলার করা
### অবজেক্ট লিটারাল ব্যবহার করে
জাভাস্ক্রিপ্ট-এ `{}` ব্যবহার করে সবথেকে সহজে অবজেক্ট ডিকলার করা যায়। 
```
let obj = {};
obj.name = 'Muhid';
obj["age"] = 25;

let obj2 = {
   "name": 'Muhid',
   age: 25
};
```
যেহেতু অবজেক্ট-এ `key` এমপ্টি স্ট্রিং সহ যেকোন স্ট্রিং হতে পারে তাই আমরা এর কোটস `""` গুলো ব্যবহার না করেই ডিকলার করতে পারি, যদি স্ট্রিং এ কোন স্পেস না থাকে।

অবজেক্ট-এর মধ্যে নেস্টেড অবজেক্টও এড করা যায়।
```
let obj = {
   name: "Muhid",
   age: 25,
   details: {
      hobbies: ["Walking", "Plying cricket"],
      Gender: "Male",
   }
}
```
অবজেক্ট-এর মধ্যে ফাংশনও ডিকলার করা যায়, এই ফাংশনকে `method` বলে।
```
let obj = {
   name: 'Muhid',
   getName: function() {
      return this.name;
   }
}

console.log(obj.getName());
//"Muhid"
```
### `new` কীওয়ার্ড ব্যবহার করে অবজেক্ট তৈরি করা
```
let obj = new Object();
obj.name = "Muhid";
obj.age = 25;
obj.getDetails = function(){
  return `${this.name} is ${this.age} years old`;
};

console.log(obj.getDetails());
//"Muhid is 25 years old"
```
### কনস্ট্রাক্টর ব্যবহার করে অবজেক্ট তৈরি করা
```
function Obj(name, age){
   //Properties
   this.name = name;
   this.age = age;

   //Methods
   this.getDetails = function(){
     return `${this.name} is ${this.age} years old`;
   }
}

let person = new Obj("Muhid", 25);
console.log(person.getDetails());
//"Muhid is 25 years old"

let person2 = new Obj("Roman", 24);
console.log(person2.getDetails());
//"Roman is 24 years old"
```
## অবজেক্ট-এর ডেটা রিড করা
### `.` নোটেশন ব্যবহার করে ডেটা রিড করা
আমরা `.` নোটেশন ব্যবহার করে অবজেক্ট-এর ডেটা রিড করতে পারি, যদি ঐ `key` এর মধ্যে কোনো স্পেস না থাকে।
```
let obj = {
   name: "Muhid",
   "what is this": "Example",
   "my age": 25
};
obj.name;
//"Muhid"

obj.what is this
//Uncaught SyntaxError: Unexpected identifier
```
স্পেস আছে এমন `key` দিয়ে প্রোপার্টি এক্সেস করলে ইরর দেখায়।
### `[]` ব্যবহার করে ডেটা রিড করা
আমরা যখন নিশ্চিত নই যে `key` এর মধ্যে স্পেস আছে কিনা, তখন আমারা `[]` ব্যবহার করতে পারি।
```
let obj = {
   name: "Muhid",
   "what is this": "Example",
   "my age": 25
};

obj["name"];
//"Muhid"

obj["what is this"];
//"Example"

obj["my age"];
//25
```
`.` এর পরে যে ওয়ার্ড ব্যবহার করা হয় তা অবজেক্ট লিটারাল হিসেবে ইন্টারপ্রেট করা হয়। `[]` এর ক্ষেত্রে ব্যবহৃত ওয়ার্ডটি ইভালুয়েট করা হয় তারপর ঐ ইভালুয়েট করা ওয়ার্ডে এসাইন করা ভেলু রিটার্ন করা হয়।
```
let obj = {
   1: "one",
   2: "two",
   3: "three"
};

for(let i = 1; i <= 3; i++){
     console.log(obj.i);
}
//undefined
//undefined
//undefined

for(let i = 1; i <= 3; i++){
     console.log(obj[i]);
}
//"one"
//"two"
//"three"
```
প্রথম লুপে `.` ব্যবহার করে ডেটা রিড করার সময় `undefined` দেখায়, কারণ এখানে `i` কে প্রোপার্টির `key` হিসেবে ট্রিট করা হয়েছে। যেখানে `i` নামে কোনো প্রোপার্টি অবজেক্টটিতে নেই।

দ্বিতীয় লুপে `i` কে ইভালুয়েট করা হয়েছে `obj[i]` এর মধ্যে এবং এটি `obj[1]` এ রুপান্তরিত হয়েছে ও `one` রিটার্ন করেছে।
### অবজেক্ট-এ নেই এমন প্রোপার্টি হ্যান্ডেল করা
যেসব প্রোপার্টি অবজেক্ট-এর মধ্যে নেই সেগুলো রিড করলে `undefined` রিটার্ন করবে
```
let obj = {
   first_name: "Muhid"
};

obj.first_name;
//"Muhid"

obj.last_name;
//undefined
```
আমরা `||` অপারেটর ব্যবহার করে যেসকল প্রোপার্টি এক্সিস্ট করেনা তাদের পরিবর্তে ডিফল্ট ভ্যালু সেট করতে পারি।
```
let lastName = obj.last_name || "Hossain";
//"Hossain"
```
এক্সিস্ট করে না এমন কোন প্রপার্টির মধ্যের প্রপার্টি এক্সেস করলে এরর দেখাবে। `&&` অপারেটর ব্যবহার করে এরর রোধ করা যায়।
```
obj.last_name;
//undefined

obj.last_name.intial
//Uncaught TypeError: Cannot read property 'intial' of undefined

obj.last_name && obj.last_name.intial
//undefined
```
`&&` অপারেটর ডান পাশের এক্সপ্রেশন তখনই ইভ্যালুয়েট করবে যখন বাম পাশের এক্সপ্রেশন `true` হবে।

## অবজেক্ট-এর ভ্যালু আপডেট করা
আমরা নতুন ভ্যালু অ্যাসাইন করে অবজেক্ট-এর ভ্যালু আপডেট করতে পারি। যদি ঐ প্রোপার্টি আগে থেকে বিদ্যমান না থাকে তাহলে এটি নতুন প্রোপার্টি অ্যাড করবে।
```
let obj = {
   name: "Muhid"
}

obj.name = "Roman";
obj.name;
//"Roman"

obj.age = 25;
obj.age;
//25

obj["gender"] = "Male";
obj["gender"];
//"Male"
```
অন্য কোন অবজেক্ট-এর ভ্যালু কপি করার সময় মনে রাখতে হবে যে অবজেক্ট রেফারেন্স হিসেবে পাস হয় কখনোই কপি হয় না।
```
let obj = {};

let person = obj;
person.name = "Muhid";

let person2 = obj.name;
person2;
//"Muhid"
```
এখানে আমরা `person.name` এ ভ্যালু এসাইন করেছি কিন্তু আমরা যখন `obj.name` এর ভ্যালু এক্সেস করছি তখন একই ভ্যালু পাচ্ছি কারণ আমরা একই অবজেক্টকে রেফার করছি।
```
//Referencing to the same object
let a = b = c = {};

//Referencing to the different objects
let a = {}, b = {}, c = {};
```
## জাভাস্ক্রিপ্ট-এ অবজেক্ট কপি করা
### `Shallow` কপি
`Shallow` কপি করার জন্য আমরা `Object.assign(To, From)` মেথড ব্যবহার করব যা একটি অবজেক্টকে অন্য অবজেক্টে কপি করে।
```
let obj = {
   name: "Muhid",
   age: 25,
   details: {
     gender: "Male"
   }
};

let copy = Object.assign({}, obj);
copy.name;
//"Muhid"

copy.age
//25

copy.details.gender;
//"Male"

//Update the gender
obj.details.gender = "Female";

copy.details.gender;
//"Female"
```
দেখা যাচ্ছে যখন আমরা `obj.details.gender = "Female"` এর ভ্যালু আপডেট করছি তা কপি অব্জেক্ট `copy.details.gender` মধ্যে রিফ্লেক্ট করছে।
`Shallow` কপি এর ক্ষেত্রে নেস্টেট অবজেক্ট রেফারেন্স হিসেবেই পাস করা হয়।
### `Deep` কপি
আমরা ডিপ কপি করার জন্য `JSON.parse()` এবং `JSON.stringify()` একসাথে ব্যবহার করব।
```
let obj = {
   name: "Muhid",
   age: 25
};

let copy = JSON.parse(JSON.stringify(obj));
copy.name;
//"Muhid"

copy.age
//25
```
## অবজেক্টকে প্রটো-টাইপের সাহায্যে এক্সটেন্ড করা
জাভাস্ক্রিপ্ট-এ সকল অবজেক্ট প্রোটো-টাইপের সাথে লিংক করা থাকে যেখান থেকে আমরা বিভিন্ন প্রপার্টি এবং মেথড ব্যবহার করতে পারি।
```
let obj = {};

obj.name = "Muhid";
obj.age = 25;
obj.prototype.getDetails = function(){return `${this.name} is ${this.age} years old`};

console.log(obj.getDetails());
//"Muhid is 25 years old"
```
অবজেক্ট এর ভ্যালু এক্সেস করার সময় যদি ওই প্রোপার্টি না থাকে তাহলে প্রোটো-টাইপের মধ্যে খুঁজে দেখবে। যদি প্রোটো-টাইপের মধ্যেও না থাকে তাহলে `undefined` রিটার্ন করবে। এই প্রোটো-টাইপ চেইনের মধ্যে খুঁজে দেখা কে `Delegation` বলে।
## অবজেক্ট-এর প্রপার্টি ডিলিট করা
আমরা `delete` অপারেটর ব্যবহার করে অবজেক্ট থেকে প্রোপার্টি রিমুভ করতে পারি। যদি অবজেক্ট-এর মধ্যে প্রোপার্টিটি না থাকে তাহলে এটি সম্পূর্ণ প্রসেস ইগনোর করে যাবে।
```
let obj = {};

obj.name = "Muhid";
obj.age = 25;

//Add properties and Methods inside the prototype.
obj.prototype.age = 24;
obj.prototype.getDetails = function(){return `${this.name} is ${this.age} years old`};

console.log(obj.getDetails());
//"Muhid is 25 years old"

//Remove age
delete obj.age;

console.log(obj.getDetails());
//"Muhid is 24 years old"
```
এটি শুধু অবজেক্টের প্রপার্টি ডিলিট করবে এটি অবজেক্টের সাথে লিঙ্ক করা প্রটো-টাইপ থেকে কিছু রিমুভ করবে না। তাই যদি প্রপার্টিটি প্রোটো-টাইপের মধ্যে থাকে তাহলে তা এক্সেস করবে।
## প্রোপার্টি বা মেথড অবজেক্ট এর মধ্যে বিদ্যমান কিনা চেক করা
### `hasOwnProperty()` ব্যবহার করে
আমরা `hasOwnProperty()` মেথড ব্যবহার করে অবজেক্ট এর মধ্যে প্রোপার্টি বা মেথডটি বিদ্যমান কিনা তা চেক করতে পারি। এটি প্রটো-টাইপ চেইনের মধ্যে বিদ্যমান প্রোপার্টি চেক করবে না।
```
let obj = {
    name: "Muhid",
    age: 25,
    getDetails: function(){
       return `${this.name} is ${this.age} years old`;
    }
};

//Adding property to prototype
obj.prototype.gender = "Male";

console.log(obj.hasOwnProperty("name"));
//true

console.log(obj.hasOwnProperty("age"));
//true

console.log(obj.hasOwnProperty("getDetails"));
//true

console.log(obj.hasOwnProperty("gender"));
//false
```
### `in` অপারেটর ব্যবহার করে
আমরা `in` অপারেটর ব্যবহার করে অবজেক্ট-এ প্রপার্টি বিদ্যমান কিনা চেক করতে পারি। এটি প্রটো-টাইপ চেইনের মধ্যে বিদ্যমান প্রপারটিও চেক করবে।
```
let obj = {
    name: "Muhid",
    age: 25,
    getDetails: function(){
       return `${this.name} is ${this.age} years old`;
    }
};

//Adding property to prototype
obj.prototype.gender = "Male";

console.log("name" in obj);
//true

console.log("age" in obj);
//true

console.log("getDetails" in obj);
//true

console.log("gender" in obj);
//true
```
## অবজেক্ট-এ লুপ চালানো
### `for...in` লুপ ব্যবহার করে
আমরা `for...in` লুপ ব্যবহার করে একটি অবজেক্ট-এর সকল প্রপার্টির উপর লুপ চালাতে পারি।
```
let obj = {
    name: "Muhid",
    age: 25,
    getDetails: function(){
       return `${this.name} is ${this.age} years old`;
    }
};

//Adding property to prototype
obj.prototype.gender = "Male";

for(let key in obj){
   console.log(obj[key]);
}

//"Muhid"
//25
/*
function () {
  return `${this.name} is ${this.age} years old`;
}
*/
//"Male"
```
এটি একটি অবজেক্ট-এর সকল প্রপার্টির উপর লুপ চালায় এমনকি প্রোটো-টাইপ চেইনের মধ্যেও। আমরা শুধু বর্তমান স্কোপের মধ্যে বিদ্যমান প্রোপার্টির উপর লুপ চালানোর জন্য `hasOwnProperty()` ব্যবহার করতে পারি।
```
for(let key in obj){
   if(obj.hasOwnProperty(key)){
     console.log(obj[key]);
   }
}

//"Muhid"
//25
/*
function () {
  return `${this.name} is ${this.age} years old`;
}
*/
```
এখানে বিদ্যমান মেথডটির সোর্স কোড প্রিন্ট হয়েছে কারণ আমরা মেথডটি `()` ব্যবহার করে ইভালুয়েট না করে এক্সেস করেছি। আমরা চাইলে টাইপ চেক করে এটি বন্ধ করতে পারে।
```
for(let key in obj){
   if(obj.hasOwnProperty(key) && typeof obj[key] !== 'function'){
     console.log(obj[key]);
   }
}

//"Muhid"
//25
```
### `Object.keys()` ব্যবহার করে
`Object.keys()` একটি অবজেক্ট নেয় এবং অবজেক্ট-এর `key` গুলোকে অ্যারে আকারে রিটার্ন করে। এটি প্রটো-টাইপ চেইনের `key` গুলো এক্সেস করে না তাই এটি ব্যবহার করা নিরাপদ।
```
console.log(Object.keys(obj));

//["name", "age", "getDetails"]
```
আমরা এই `key` গুলোর অ্যারেটিকে অবজেক্ট-এর মধ্যে লুপ চালানোর জন্য ব্যবহার করতে পারি।
#### `for...of` লুপ
```
//For of loop
for(let key of Object.keys(obj)){
  if(typeof obj[key] !== 'function'){
     console.log(obj[key]);
   }
}

//"Muhid"
//25
```
#### `forEach` লুপ
```
//For each loop
Object.keys(obj).forEach((key) => {
  if(typeof obj[key] !== 'function'){
     console.log(obj[key]);
   }
});

//"Muhid"
//25
```
অবজেক্ট হলো জাভাস্ক্রিপ্ট-এর হৃদয় এবং অবজেক্ট প্রতিনিয়ত উন্নত হচ্ছে।