Prototype - the foundation of JavaScript

প্রোটোটাইপ জাভাস্ক্রিপ্ট এর একটি গুরুত্বপূর্ণ টপিক। এটা আমরা একদম শুরু থেকে জানব। ইউসকেস গুলো দেখে দেখে শিখব। চলুন একটা অবজেক্ট বানানো যাক।

let person = {}; person.name = 'Sumit Saha'; person.age = '45'; person.eat = function () { console.log('I am eating'); }; person.play = function () { console.log('I am playing'); };

এখন আমাদের অ্যাপে তো একটা অবজেক্ট থাকবে না থাকবে অনেক অনেক অবজেক্ট যার মধ্যে এমন কিছু প্রোপার্টি থাকবে যাদেরকে আমরা একাধিকবার ব্যবহার করব। যার জন্য মেমোরিতে আমাদের অনেক জায়গা নিয়ে নিবে। এটাও কখনো ভালো পারফোমেন্স অ্যাপ হবে না এর জন্য আমরা কমন প্রোপার্টি গুলো আলাদা আরেকটা ফাংশন এ লেখতে পারি যাতে করে পরে আমরা তা রেফারেন্স হিসাবে ব্যবহার করতে পারি। এবং person কেও আমরা একটা ফাংশন এ রাখতে পারি।

const personMethod = { eat() { console.log('I am eating'); }, play() { console.log('I am playing'); }, }; function Person(name, age) { let person = {}; person.name = name; person.age = age; person.eat = personMethod.eat; person.play = personMethod.play; return person; }

এভাবে আমরা রেফারেন্স মাধ্যমে ফাংশন গুলো ব্যবহার করতে পারি যাতে করে আমাদের মেমোরিতে স্পেস কমাতে পারি। কিন্তু এখানে প্রব্লেম আছে

const personMethod = { eat() { console.log('I am eating'); }, play() { console.log('I am playing'); }, sleep() { console.log('I am sleeping'); }, }; function Person(name, age) { let person = {}; person.name = name; person.age = age; person.eat = personMethod.eat; person.play = personMethod.play; person.sleep = personMethod.sleep; return person; } const sakib = Person('Sakib', 35); const tamim = Person('Tamim', 30);

যদি আমাদের আরো কিছু মেথড্‌ অ্যাড করতে হয় তাহলে personMethod অ্যাড করতে হবে পাশাপাশি Person এ ও করতে হবে যেটা একটু কামবারসিং।

এর থেকে সমাধান পেতে আমরা ব্যবহার করতে পারি Object.create() । চলুন এ সম্পর্কে নিচে জানা যাক।

const player = { name: 'Mashrafi', age: 32, roll: 'Criper', }; const person = Object.create(player); console.log(person); //output - {} console.log(person.name); //output - Mashrafi

উপরের কোডটি লক্ষ্য করুন তাহলে বুঝতে পারবেন যে Object.create() কি কাজ করে যদি আমাদের কোনো কমন অবজেক্ট অথবা অ্যারে থাকে যাকে আমাদের প্রতিটি person অবজেক্ট এর সাথে রাখতে হবে তাহলে আমরা Object.create() এর মধ্যে অই কমন অবজেক্টটি দিয়ে দেবো তাহলে Object.create() অইটা বেস করে আরেকটা নিউ অবজেক্ট বানাবে। এখন দেখুন যখন আমার person কে console.log(person) করছি তখন কিন্তু পাচ্ছি {}। কিন্তু আবার person.name কে অ্যাক্সেস করতে চাইলে তা করতে পারতেছি। তার মানে হলো আমার চাইল্ড থেকে পেরেন্ট এর প্রোপার্টি অ্যাক্সেস করতে পারতেছি অথচ person কে লগ করলে পেরেন্ট এর কোনো প্রোপার্টি দেখতে পাচ্ছি না। এখন যদি আমার পেরেন্ট এ আরো প্রোপার্টি অ্যাড করি তাহলে daynamiclly চাইল্ড ও তা পেয়ে যাবে এবং অ্যাক্সেস করতে পারবে। চলুন এটা কাজে লাগিয়ে আমাদের সমস্যা টা সমাধান করে নিই।

const personMethod = { eat() { console.log('I am eating'); }, play() { console.log('I am playing'); }, sleep() { console.log('I am sleeping'); }, }; function Person(name, age) { let person = Object.create(personMethod); person.name = name; person.age = age; return person; } const sakib = Person('Sakib', 35); console.log(sakib.eat()); //output - I am eating const tamim = Person('Tamim', 30);

অর্থাৎ এখন আমাদের পেরেন্ট এ আরো মেথড্‌ অ্যাড হলে আমাদের চাইল্ড এসে এসে অ্যাড করতে হবে না, অটোমেটিক্যালি হয়ে যাবে। কিন্তু এটা হচ্ছে কিভাবে ওটা আমাদের জানতে হবে। এটা হচ্ছে প্রোটোটাইপের কারনে। এখন আসছে প্রোটোটাইপ। এখন থেকে মজাটা শুরু হবে।

একটু খেয়াল করুন। এখন যে কোডটি আমরা লিখেছি তাকে ও আমার আরো ইম্প্রোভ করতে পারি। এতক্ষন যা করলাম তা হচ্ছে প্রোগ্রামিং এর একটি পরিচিত প্যাট্রান এই ওয়েতে আমরা কোড কে আরো বেটার অয়েতে ব্যবহার করতে পারি।

কিন্তু খেয়াল করুন এখানে ও আমাদেরকে একটা অবজেক্ট কে বাইরে মেইন্টেইন করতে হচ্ছে। Person ফাংশন কে এসিস্ট করার জন্য আমাদের personMethod কে দরকার হচ্ছে। এই বেপার টাও কেমন জানি। বিল্টইন কিছু একটা কি নাই এটা কে হ্যান্ডেল করার জন্য।

Prototype

চলুন একটা ফাঁকা ফাংশন নেওয়া যাক।

function test() {} console.log(test.prototype);

ফাংশন কিন্তু নিজে একটি অবজেক্ট। উপরের আমার ফাংশন এ কিন্তু কিছু নেই কিন্তু তাকে console.log(test.prototype) দিলে কিছু পাচ্ছি কি পাচ্ছি তা পরে কিন্তু কিছু একটা পাচ্ছি।

output

আবার যদি আমরা console.dir(test) করি তাহলে এখানে এক্সপান্ড করলে আমরা prototype নামে একটি প্রোপার্টি পাচ্ছি। কারনে console.log(test.prototype) দিলে আমরা prototype কে পাচ্ছি।

তাহলে প্রোটোটাইপ কি?

প্রোটোটাইপ হচ্ছে সিম্পল প্রোপার্ট অব এ ফাংশন যা একটি ফাংশন কে পয়েন্ট করে রাখে। জাভাস্ক্রিপ্ট যেকোনো ফাংশন এ লেখা হোক না কেনো তার একটা প্রোপার্টি হচ্ছে prototype যা একটা object কে পয়েন্ট করে।

Object.create() দিয়ে আমরা কোনো Object create করলে আমরা পেরেন্ট এর সকল মেথড গুলো পেয়ে যাকে আমাদের ফাংশন এ আলাদা করে আর রাখতে হতো না। কিন্তু এর জন্য আমাদের বাহিরে আলাদা আরেকটি অব্জেক্ট ডিফাইন করা লাগতেছে।

এখন খেয়াল করুন যেহেতু প্রত্যেক ফাংশন এর ই প্রোটোটাইপ নামে একটা অব্জেক্ট আছেই কেনো নয় আমাদের personMethod গুলো কে আমরা প্রোটোটাইপ অব্জেক্ট এ রাখবো না । চলুন personMethod থেকে অব্জেক্ট টা বের করে আমাদের ফাংশন প্রোটোটাইপ এ রাখা যাক।

function Person(name, age) { let person = Object.create(Person.prototype); person.name = name; person.age = age; return person; } Person.prototype = { eat() { console.log('I am eating'); }, play() { console.log('I am playing'); }, sleep() { console.log('I am sleeping'); }, }; const sakib = Person('Sakib', 35); console.log(sakib.eat()); //output - I am eating const tamim = Person('Tamim', 30);

দেখুন মেথড গুলো বের করে এনে ফাংশন এর নিজেরই প্রোপার্টি prototype এর মধ্যে এ রেখে দিলাম আমাদের কোড একই ভাবে কাজ করছে।

এখন বুঝতে পারছেন প্রোটোটাইপ এর মজা টা। কেনো কিভাবে প্রোটোটাইপ কে আমি ব্যবহার করেছি।

এখানে class এর কন্সেপ্ট ও চলে আসে অন্যান্য প্রোগ্রামিং ল্যাঙ্গুয়েজ গুলো যে কাজ গুলো class সিন্টেক্স দিয়ে করে ভ্যানিলা জাভাস্ক্রিপ্ত এ কিন্তু class নাই অই কাজটাই জাভাস্ক্রিপ্ট prototype দিয়ে করে থাকে। পেরেন্ট এর সকল প্রোপার্টি গুলো চাইল্ড এ prototype এর মাধ্যমে ইনহেরিট inherite করে থাকে। যেটাকে আমার inheritance বলি। অন্যান্য ল্যাঙ্গুয়েজ এ এর কাজ টা করে class জাভাস্ক্রিপ্ট এই একই কাজটা করে থাকে prototype

Constructor Function

function Person(name, age) { let person = Object.create(Person.prototype); person.name = name; person.age = age; return person; }

উপরের এই ফাংশন টা কে বলা কন্সট্রাক্টর ফাংশন। বুঝার উপায় হলো ফাংশন এর নাম শুরু হবে কেপিটাল লেটার দিয়ে। জাভাস্ক্রিপ্ট সকল ফাংশন বাই ডিফ্লট কন্সট্রাক্টর ফাংশন। কারন এই ফাংশন থেকে আমার একটা অব্জেক্ট কন্সট্রাক্ট করতে পারছি।

const sakib = Person('Sakib', 35); const tamim = Person('Tamim', 30);

এখন পর্যন্ত আমরা কি কি জানলামঃ-

  • কিভাবে কন্সট্রাক্টর ফাংশন তৈরি করা যায়।
  • কিভাবে ফাংশন প্রোটোটাইপ এর মধ্যে আমাদের তৈরিকৃত মেথড রাখতে পারি।
  • Object.create() দিয়ে কিভাবে অব্জেক্ট তৈরি করতে পারি যা পেরেন্ট এর প্রোপার্টি কেও পেয়ে যায়।

এতো গুলো কাজ করার আমাদের মেইন উদ্দেশ্য ছিলো, কন্সট্রাক্টর ফাংশন এর সকল কমন ফাংশন গুলো কে তার প্রত্যেকটি ইন্সটেন্স এর মধ্যে সমান ভাবে সেয়ার করে দেওয়া।

new keyword

উপরের ফাংশন এর ইন্সটেন্স তৈরি করার বেপার টা আমরা জাভাস্ক্রিপ্ট এ আবার অন্য ভাবে ও করতে পারি। new কিওয়ার্ড দিয়ে।

const sakib = new Person('Sakib', 35); const tamim = new Person('Tamim', 30);

এভাবে লিখলে আমাদের ফাংশন এ একটু পরিবর্তন আনতে হবে। চলুন তা দেখে নেওয়া যাক।

function Person(name, age) { // let person = Object.create(Person.prototype); this.name = name; this.age = age; // return person; } Person.prototype = { eat() { console.log('I am eating'); }, play() { console.log('I am playing'); }, sleep() { console.log('I am sleeping'); }, }; const sakib = new Person('Sakib', 35); const tamim = new Person('Tamim', 30);

অর্থাৎ আমাদের কে let person = Object.create(Person.prototype) and return person; আর লিখতে হবে না এবং Person.name = name; এর পরিবর্তে this.name = name লিখতে হবে। বলা যায় জাভাস্ক্রিপ্ট আমাদের হয়ে এই দুইটা কাজ করে দেয় এবং this দিয়ে তা ডিফাইন করে দেয়।

// let this = Object.create(Person.prototype); // return this;

রিয়েক্ট এর ফাংশন কন্সট্রাক্টর কিন্তু এভাবেই কাজ করে থাকে।

তাহলে এখন আমরা new কিওয়ার্ড দিয়ে অব্জেক্ট তৈরি করতে পারতেছি। অন্যান্য লাঙ্গুইয়েজে কিন্তু এভাবে অব্জেক্ট তৈরি করে থাকে। এখন কিন্তু জাভাস্ক্রিপ্ট এ class ও ব্যবহার করতে পারি।
খেয়াল করুন ভেনিলা জাভাস্ক্রিপ্ট এ কিন্তু এই class বুঝে না এটা জাভাস্ক্রিপ্ট বিভিন্ন ভার্সন এর মাধ্যমে সিন্টেক্টিক্স পরিবর্তনের মাধ্যমে এগুলো সাপোর্ট দিয়ে থাকে যাতে করে অন্যান্য লাঙ্গুইয়েজ থেকে প্রোগ্রামারগন এখানে এসে কাজ করতে পারে।

Class keyword

চলুন আমাদের এই কোডটা কে Es6 এর Class পরিবর্তন করে নি। তাহলে আমাদের আর Prototype লিখতে হবে না।

class Person { constructor(name, age) { this.name = name; this.age = age; } eat() { console.log('I am eating'); } play() { console.log('I am playing'); } sleep() { console.log('I am sleeping'); } } const sakib = new Person('Sakib', 35); sakib.play(); // output - I am playing const tamim = new Person('Tamim', 32);

চলুন আমরা কিছু রিয়েল এক্সামপল দেখে নিই।

যখন আমারা একটা অ্যারে ক্রিয়েট করি তখন কিভাবে লিখি।

const person = [];

এটাকে আমার আরেক ভাবে ও লিখতে পারি।

const person = new Array();

দুইটার কাজ একই জাভাস্ক্রিপ্ট আমাদের জন্য সহজ করে উপরের মতো লেখার সহজ করে দিয়েছে।

কিছু কি মিল পাচ্ছেন উপরে যে আমরা class ব্যবহার করছিলাম তখন কিভাবে সাকিব কে কন্সট্রাক্ট করছিলাম new কিওয়ার্ড দিয়ে তখন কিন্তু আমরা মেথড গুলো প্রোটোটাইপ থেকে ব্যবহার করছি। ঠিক একই ভাবে const person = new Array() এখানে আমার new ব্যবহার করেছি অর্থাৎ এখানে যদি person কে console.dir(person) করি দেখুন আমরা তার প্রোটোটাইপ এ কি পাই।

prototype

একটু খেয়াল করলে দেখতে পাবেন এখানে push() , pop() , shift() সকল মেথড গুলো আছে। এখন বুঝতে পারছেন কেনো আমরা খালি অ্যারে ডিফাইন করে বা কিছু ভ্যালু অ্যাড করে কিন্তু এই push() , pop() , shift() মেথড গুলো না লিখে কিভাবে ব্যবহার করছি। এখানে person চাইল্ড এবং তার পেরেন্ট হচ্ছে Array() তাই Array() সকল মেথড গুলো চাইল্ড এইভাবে prototype এর মাধ্যমে ইনহেরিট করে ব্যবহার করছে। এভাবে তার ও চাইল্ড তার ও চাইল্ড মেথড গুলো পেয়ে থাকে যাকে আবার আমরা বলি প্রোটোটাইপ চেইন। আমরা push() , pop() , shift() বলি এগুলো জাভাস্ক্রিপ্ট এর বিল্ট ইন ফাংশন। আশা করি এখন বুঝতে পারছেন। এটা তেমন কিছুই না এটা হলো জাভাস্ক্রিপ্ট এর প্রোটোটাইপ এর কন্সেপ্ট।

জাভাস্ক্রিপ্ট এ Object খুবই পাওয়ারফুল একটা জিনিস। Object , prtotype এর কন্সেপ্ট গুলো খুবই গুরুত্বপূর্ন। এগুলো কন্সেপ্ট পরিষ্কার থাকলে পরে অনেক ইনজয় করবেন জাভাস্ক্রিপ্ট নিয়ে কাজ করার সময়। 💘💘