JavaScript 'this' keyword article in Bangla - .call(), .apply() and .bind()
মনে করুন আপনার অনেক গুলো বাড়ি আছে, এখন আপনি একজন বাড়ি রঙ করে এইরকম লোক কে সাথে নিয়ে আপনার একটা বাড়ি তে আছেন এবং তাকে বলতেছেন যে এই বাড়ি টি রঙ করতে হবে। আপনি কিন্তু বলছেন না যে এই রোড অমুক জায়গার বাড়িটি রঙ করতে হবে। অর্থাৎ আপনি এখন যেখানে আছে তাকে বোঝানোর জন্য আমরা এই শব্দটি ব্যবহার করতে পারি। ইংরেজিতে আমরা যাকে this বলতে পারি। আর যে রঙ করবে সেই কিন্তু বুঝে যাবে এই দিয়ে এখন যেখানে আছে সেই বাড়িকেই বোঝানো হয়েছে।
জাভাস্ক্রিপ্ট এ this এভাবেই কাজ করে থাকে। এই this বিভিন্ন কাজে ফাংশন কে রিইউজেবল করতে হেল্প করে থাকে।
জাভাস্ক্রিপ্ট এ this চারটি রুল অনুযায়ী চলে। এই চারটি রুল বুঝে ফেললে কোন this কোথায় কাকে কোন অব্জেক্ট কে পয়েন্ট করছে তা আর বুঝতে সমস্যা হবে না।
- implicit binding
- explicit binding
- new binding
- window binding
implicit binding
চলুন একটা সিম্পল অব্জেক্ট লিখি।
const sakib = { name: 'Shakib', age: 35, printName: function () { console.log(this.name); }, }; sakib.printName();
উপরের কোডে যে this
ব্যবহার করা হয়েছে এখানে এই this
কাকে পয়েন্ট করবে কারন এখানে যদি আমাদের অই উপরের বাস্তবিক উদাহরণ টা নিয়ে আসি তাহলে ত এই ফাংশন এর ভিতর এর দুনিয়া কে বোঝানো হচ্ছে নাকি সাকিব অব্জেক্ট কে বোঝানো হচ্ছে। জাভাস্ক্রিপ্ট ত মানুষের মতো বুঝে নিবে না। এটা বুঝার জন্য আমাদের দেখতে হবে কাকে কল করা হচ্ছে এখানে printName()
কে প্রথমে এই ফাংশন বডির কাছে যেতে হবে। তারপর দেখতে হবে এই printName()
এর পূর্বে কোনো .
দিয়ে কোনো অব্জেক্ট আছে কি না যদি থাকে তাহলে এই printName()
ফাংশন এ ব্যবহার করা this
হচ্ছে .
এর পূর্বে ইমিডিয়েটলি এই sakib
অব্জেক্ট এর।
কিন্তু এই নিয়ম অ্যারো ()=>
ফাংশন এর ক্ষেত্রে প্রযোজ্য নয়।
কিন্তু যদি এমন হয় যে sakib
অব্জেক্ট এ name
নামে কোনো প্রোপার্টি না থাকে তাহলে window.object
এর মতো কাজ করবে।
চলুন আরেকটি ওয়েতে দেখা যাকঃ-
function printNameFunction(obj) { obj.printName = function () { console.log(`${this.name}`); }; } const sakib = { name: 'Sakib', age: 35, }; const tamim = { name: 'Tamim', age: 32, }; printNameFunction(sakib); printNameFunction(tamim); sakib.printName(); //output - Sakib tamim.printName(); //output - Tamim
এখানেও implecit binding
রুল কাজ করছে। আমার কল করছি printName()
ফাংশনকে, তার পূর্বে .
দিয়ে কিছু একটা অব্জেক্ট আছে। এই ক্ষেত্রে printName()
ফাংশন এর this
হবে .
এর পূর্বে ইমিডিয়েটলি অব্জেক্টটি।
var Person = function (name, age) { return { name: name, age: age, printName: function () { console.log(this.name); }, fatherName: { name: 'Mr. Ali', printName: function () { console.log(this.name); }, }, }; }; const sakib = Person('Sakib', 35); sakib.printName(); //output - Sakib sakib.fatherName.printName(); //output - Mr. Ali
দেখুন এখানে কিন্তু একটু ব্যতিক্রম আছে প্রথমে যখন sakib.printName();
কল করা হয় তখন তার ইমিডিয়েট অব্জেক্ট হচ্ছে সাকিব অব্জেক্ট তাই const sakib = Person('Sakib', 35);
এর name
আউটপুট হবে।
কিন্তু যখন sakib.fatherName.printName();
একে কল করা হয় তখন কিন্তু আমাদের কল করা ফাংশন এর ইমিডিয়েট অব্জেক্ট হচ্ছে fatherName
তাই এটা হবে this
, তাই আউটপুট আসছে Mr. Ali
। যদি আপনার fatherName
অব্জেক্ট এ name
প্রোপার্টি না থাকে তাহলে সিম্পল undefined
আসবে। এটাই হচ্ছে implecit binding।
explicit binding
explicit binding এ তিনটি মেথড কাজ করে থাকে।
- call()
- apply()
- bind()
var printName = function () { console.log(this.name); }; var sakib = { name: 'Sakib', age: 35, }; printName.call(sakib);
এখানে দেখুন printName()
ফাংশন অন্য কন্টেক্সে গ্লোবাল এ আছে তাহলে এই ফাংশন এ ব্যবহার করা this
কে আমার স্পট ভাবে বলে দিতে পারি এটাকেই বলা হচ্ছে implicit binding এটা কে করার জন্য ফাংশন কে call()
দিলে ইনবোক করে দিতে পারি এবং প্যারামিটার হিসেবে যেই অব্জেক্টকে this
করতে চাচ্ছি তাকে আমরা দিয়ে দিতে পারি। printName.call(sakib);
এখন যদি printName
ফাংশন এর প্যারামিটার দরকার হয় তখন কিভাবে দিবো, এটি করার জন্য call()
এর সেকেন্ড প্যারামিটার যত ইচ্ছে তত ভ্যালু পাঠাতে পারি যাকে আমরা printName
ফাংশন এ ব্যবহার করতে পারবো।
var printName = function (v1, v2, v3) { console.log(`${this.name} ${v1}, ${v2}, ${v3}`); }; var sakib = { name: 'Sakib', age: 35, }; printName.call(sakib, 'Handsome', 'All-rounder', 'Best Player'); //output - Sakib Handsome, All-rounder, Best Player
এখন call()
এর সেকেন্ড প্যারামিটার এ দেওয়া সকল ডাটা গুলো যদি একটা অ্যারে হতো তাহলে কি call()
ব্যবহার করতে পারতাম - না। কারন call()
অ্যারে নেয় না। সমধান হলো call()
এর মতো explicit ভাবে this
কে বলে দেয় এবং সেকেন্ড প্যারামিটার এ অ্যারে নেয় এমন মেথড হলো apply()
।
var printName = function (v1, v2, v3) { console.log(`${this.name} ${v1}, ${v2}, ${v3}`); console.log(v); }; var sakib = { name: 'Sakib', age: 35, }; const v = ['Handsome', 'All-rounder', 'Best player']; printName.apply(sakib, v); //output - Sakib Handsome, All-rounder, Best Player
আরেকটি কন্সেপ্ট হলো bind()
এটি ও call()
এর মতো কাজ করে কিন্তু পার্থক্য হলো call()
কে যে ফাংশন এর সাথে ব্যবহার করা হয় তাকে কল করে দেয়। আর bind()
ফাংশন কে কল করে না ফাংশন বডি কে রিটার্ন করে দেয়। তাই bind()
ব্যবহার করলে তাকে আগে একটি ভেরিয়েবল এ স্টোর করতে হবে। তারপর তাকে কল করে দিতে হবে। এই হলো call()
and bind()
এর মধ্যে পার্থক্য।
var printName = function (v1, v2, v3) { console.log(`${this.name} ${v1}, ${v2}, ${v3}`); console.log(v); }; var sakib = { name: 'Sakib', age: 35, }; const newFunc = printName.bind(sakib, 'Handsome', 'All-rounder', 'Best player'); newFunc(); //output -Sakib Handsome, All-rounder, Best Player
new binding
যারা আমার লেখা প্রোটোটাইপ এর আর্টিকেলটি পরেছেন তাদের এর new binding বুঝতে সুবিধা হবে। সেখানে দেখানো হয়েছিলো কিভাবে ফাংশন কন্সট্রাক্টর মাধ্যমে অব্জেক্ট তৈরি করা যায়। চলুন কন্সট্রাক্টর অব্জেক্ট বানাই-
function Person(name, age) { this.name = name; this.age = age; consolo.log(`${this.name} is ${this.age} years old`); } const sakib = new Person('Sakib', 35);
তখন বলেছিলাম এভাবে new
দিয়ে অব্জেক্ট বানানো হলে ২টি লাইন লিখতে হয় না বোঝানোর জন্য নিচে লেখা হলোঃ
function Person(name, age) { // let this = Object.create(null) this.name = name; this.age = age; consolo.log(`${this.name} is ${this.age} years old`); // return this } const sakib = new Person('Sakib', 35);
অর্থাৎ কন্সট্রাক্টর ফাংশন এ this
নামেই একটি অব্জেক্ট বানাই পরে এই অব্জেক্টেই রিটার্ন করে দেয়। এবং new
এই this
কেই পয়েন্ট করে।
window binding
চলুন প্রথমে একটি ইউসকেস বানাই।
var printName = function () { console.log(this.name); //output - undefined }; var sakib = { name: 'Sakib', age: 35, }; printName();
যদি আমরা এভাবে কল করি তাহলে কি আশার কথা। undefined
কিন্তু আনডিফাইন্ড কেনো। এখানে this.name
বলতে তো কিছুই নেই তাহলে ত এরর আশার কথা তাহলে এই this
সাম্থিকং ইজ হেপেন তাই সে name
নামে কিছু পাচ্ছে না তাই এরর না দিয়ে undefined
দিচ্ছে। আচ্ছা তাহলে this
কে console.log(this)
করে দেখা যাক।
আমার এখানে Window
অব্জেক্টকে পেয়ে যাবো। তাহলে কি বোঝা গেলো যদি উপরের চারটির মধ্যে কোনো প্রথম তিনটি কোনো রুলই গ্রহন হবে জাভাস্ক্রিট নিজে নিজে this
Window
কে পয়েন্ট করবে। এখন এটাকে থামাতে হলে অন্তত্য পক্ষে এরর দিয়ে সাবধান করার জন্য আমরা স্ক্রিপ এর সবার উপরে 'use strict'
ব্যবহার করতে পারি। এই যে এখানে this
window
কে পয়েন্ট করছে এটাই হচ্ছে window binding
। এটাকে সিউর হবার জন্য আমার এভাবে লিখে দেখতে পারি কাকে শো করে।
var printName = function () { console.log(this); console.log(this.name); //output - undefined }; var sakib = { name: 'Sakib', age: 35, }; printName();
দেখবেন কন্সলে Window
কেই পাচ্ছি। এছাড়া this === window
করলে true
পাবো। এই ছিলো this
নিয়ে সকল কন্সেপচুয়াল বেপারটা, আশা করি this
নিয়ে আর কোনো সমস্যা হবে না। 💘💘