জাভাস্ক্রিপ্ট ইএস ৬(ES6): অ্যারো (Arrow) ফাংশন ও লেক্সিক্যাল(Lexical) ‘this’ কীওয়ার্ড

জাভাস্ক্রিপ্ট এর ইএস৬ এ নতুন আরেক সংযোজন হচ্ছে অ্যারো ফাংশন। অনেকের কাছে ফ্যাট অ্যারো(Fat Arrow) ফাংশন বলেও পরিচিত। এটা আসলে নতুন কিছু নয়, জাস্ট সিন্ট্যাক্টিক্যালি দেখতে সুন্দর এবং অনেকটা ক্লিন। প্রোগ্রামিং ল্যাংগুয়েজের ওয়ার্ল্ডে সিন্ট্যাক্টিক শুগ্যার(Syntactic Sugar) বলে একটা কথা আছে। এর মানে হচ্ছে দেখতে সুন্দর লাগে, ক্লিন মনে হয় এরকম সিনট্যাক্স। যদিও অ্যারো ফাংশনের ফাংশানালিটি ইএস৫ এর ফাংশনের মতোই অনেকটা, কিন্তু কিছু পার্থক্য আছে। সেগুলো আমি একটা একটা করে এই পর্বে আলোচনা করবো।

ইএস৫ এ ফাংশন এক্সপ্রেশন আমরা এভাবে লিখিঃ

var aFunc = function() {
   console.log('A Demo ES5 Function Expression');
}

এবার এই ফাংশনকে কল করলেঃ

aFunc();

এখন সেই ফাংশনটাকেই অ্যারো ফাংশনে লিখলেঃ

const aFunc6 = () => console.log('A Demo ES6 Arrow Function');

এবার এই ফাংশন রান করাতে চাইলেঃ

aFunc6();

এখানে দেখুন এদের মধ্যে পার্থক্যগুলো। ইএস৬ এর অ্যারো ফাংশনে আমাদের function কীওয়ার্ড লাগতেছে না। আবার অন্যদিকে নতুন একটা সিনট্যাক্স => লাগতেছে। এজন্যেই এটাকে অ্যারো ফাংশন বলা হয়। আর কোড অনেকটাই ক্লিন মনে হচ্ছে অ্যারো ফাংশনের বেলায়। যে জায়গায় ইএস৫ এর ফাংশনে কয়েকলাইন লিখতে হয়েছে, বা আমাদের {} এই ব্র্যাকেটসগুলো ইউজ করতে হয়েছে, সেখানে অ্যারো ফাংশনের বেলায় লাগতেছে না।

অ্যারো ফাংশন অনেকটাই স্মার্ট। নিচে কিছু উদাহরণ দিয়ে অ্যারো ফাংশনের স্মার্টনেস দেখানো হলো।

অটোম্যাটিক রিটার্নঃ ধরি আমাদের এরকম একটা অ্যারে আছেঃ

const dob = [1996, 1986, 2017, 1989];

এখন আমি map() ইউজ করে প্রত্যেকটার জন্যে বর্তমান বয়স বের করতে চাই। মানে এখানে থাকা বছরের সাথে আমাদের বর্তমান বছর(এই লেখার সময় 2018) তুলনা করে কার কতো বয়স সেটার আরেকটা অ্যারে করতে চাই। প্রথমে ইএস৫ এঃ

const currentAge5 = dob.map(function(oneDob) {  
   return 2018 - oneDob;
})

এবার currentAge5 এ আমরা সবার বর্তমান বয়সের আরেকটা অ্যারে পাবো। map() কিভাবে কাজ করে না জেনে থাকলে এখান থেকে দেখে নিতে পারেন।

currentAge5;

এখন সেইম কোডটা যদি আমি ইএস ৬ এর আরো ফাংশন দিয়ে লিখিঃ

const currentAge6 = dob.map(oneDob => 2018 - oneDob);

এবার এটা প্রিন্ট করলে সেইম রেজাল্টই আসবেঃ

currentAge6;

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

একাধিক আর্গুমেন্টঃ উপরের উদাহরণে দেখবেন আমাদের শুধুমাত্র একটা আর্গুমেন্টই ছিলো। এখন আমরা জানি map() তিনটা আর্গুমেন্ট নেয়। এখন একাধিক আর্গুমেন্ট থাকলে অ্যারো ফাংশনে আর্গুমেন্ট গুলো অবশ্যই () ব্র্যাকেটস এর ভিতরে থাকতে হবে। এখন একটা থাকলেও সেটাকে ব্র্যাকেটস এ ঢুকাতে পারবেন, কিন্তু কোড যত কম লেখা যায় ততোই তো ভালো! আগের উদাহরণটায় দুইটা আর্গুমেন্ট থাকলেঃ

const currentAge62 = dob.map((oneDob, index) => `${index}: ${2018 - oneDob}`);

এবার এটা রান করালেঃ

currentAge62;

একাধিক লাইনঃ এখন আমাদের একাধিক লাইনের কোড থাকলে কি হবে? হ্যাঁ তখন আর অটো রিটার্ন হবে না, আমাদের বলে দিতে হবে return কীওয়ার্ড ইউজ করে জাস্ট ইএস৫ এর মতোইঃ

const currentAge622 = dob.map(oneDob => {
   const age = 2018 - oneDob;
      return age;
});

এবার এটা রান করালেঃ

currentAge622;

এখন এখানে আরেকটা জিনিস খেয়াল করবেন। অ্যারে ফাংশনের ক্ষেত্রে আমাদের ফাংশন এক্সপ্রেশন ইউজ করতে হচ্ছে। এখন ইএস৫ এর ফাংশন এক্সপ্রেশনের ক্ষেত্রেও আমরা হোইস্টিং এর কারণে একটা ফাংশন ডিফাইন করার আগে সেটাকে কল করতে পারি না। ইএস৫ এর ফাংশন স্টেটমেন্ট এ সেটা সম্ভব ছিলো হোইস্টিং এর কারণে। আর ইএস৬ এর অ্যারো ফাংশন ইউজ করতে হলে অবশ্যই আমাদের ফাংশন এক্সপ্রেশন ইউজ করতে হবে। সেজন্যে এখানে ফাংশন ডিফাইন করার আগে কল করতে পারবেন না। যেমন ইএস৫ এর ফাংশন স্টেটমেন্ট এঃ

myName();

function myName() {
   console.log('Zonayed Ahmed');
}

পুরোটা কোড একসাথে রান করলে দেখবেন কাজ করছেঃ

এখন সেইমভাবে ফাংশন এক্সপ্রেশনেঃ

myName();

const myName = function() {
   console.log('My name is Zonayed Ahmed');
}

এটা এরর আসবেঃ

এখন ইএস ৬ এর অ্যারো ফাংশন যেহেতু ফাংশন এক্সপ্রেশন, তাই হোইস্টিং এর কারণে সেইমভাবেই আপনি ফাংশন ডিফাইন করার আগে সেটাকে কল করতে পারবেন নাঃ

myName6();

const myName6 = () => console.log('My name is Zonayed');

সেইমভাবে এররঃ

এখানে আমি const ইউজ করেছি ভ্যারিয়েবল ডিক্লেয়ারেশনের বেলাতে, আপনি চাইলে let বা var যেকোনো কিছু ইউজ করতে পারবেন। এতে ফলাফলে কোনো পার্থক্য হবে না।

লেক্সিক্যাল(Lexical) 'this’ কীওয়ার্ডঃ

এতক্ষন পর্যন্ত যা আলোচনা করলাম, এগুলো সিন্ট্যাক্টিক শ্যুগার ছাড়া তেমন কিছুই না। অ্যারো ফাংশনের সবচেয়ে বড় ডিফারেন্সটা যেখানে সেটা হচ্ছে this কীওয়ার্ডের সাথে। আমরা জানি, ইএস৫ এর বেলায় একটা ফাংশন কিভাবে কল করা হচ্ছে সেটার উপর this কীওয়ার্ডের ভ্যালু অনেকটা নির্ভর করে। ইএস৫ এ প্রত্যেকটা ডিফাউনকৃত ফাংশনের নিজস্ব this এর ভ্যালু থাকে। কিন্তু ইএস৬ এর এই অ্যারো ফাংশনের নিজস্ব কোনো প্রভাব থাকে না this কীওয়ার্ডের উপর। বরং এই অ্যারে ফাংশন এর আশেপাশে যেটা থাকে, ঠিক সেখানকার this এর ভ্যালুই অ্যারো ফাংশনের ভিতরেও থাকে।

যেমন আমরা এই উদাহরণটা নিলে দেখতে পাবো ভালো করে। প্রথমে ইএস৫ এর ফাংশন ইউজ করেঃ

const lex5 = {
   aFunc: function() {
      console.log(this);
      return function() {
         console.log(this);
      }
   }
}

এই কোডে একটা অবজেক্ট এর ভিতরে মাল্টিপল ফাংশন রয়েছে। প্রথম ফাংশনে this ঠিকঠাকা lex5 কেই ইন্ডিকেট করবে। কিন্তু দ্বিতীয় ফাংশন গ্লোবাল অবজেক্ট কে ইন্ডিকেট করবে। দুইটা ফাংশন কল করলেঃ

lex5.aFunc()();

দেখুন প্রথমটা ঠিকই এর অবজেক্ট lex5 কে ইন্ডিকেট করছে। কিন্তু ভিতরের ফাংশনটা আবার গ্লোবাল অবজেক্টকে ইন্ডিকেট করেছে। এখন ইএস৫ এর ফাংশন কলের উপর this ভ্যালু ডিপেন্ড করায় এটা হয়েছে। কিন্তু সেইম কোড এখন ইএস৬ এর অ্যারো ফাংশন ইউজ করে করলেঃ

const lex6 = {
   aFunc: () => {
      console.log(this);
      return () => console.log(this);
   }
}

এখন এটা রান করালে দেখবেনঃ

এগুলো দুইটাই গ্লোবাল অবজেক্ট দেখাচ্ছে। এদের this কীওয়ার্ডের উপর কোনো প্রভাবই নেই।

আশেপাশের this অ্যারো ফাংশনের ভিতরেও সেইমঃ যেমন সেইম এই উদাহরনটাতেই আমরা দুইটা ফাংশন মিক্স করে লিখলে দেখতে পাবোঃ

const lex56 = {
   aFunc: function(){
      console.log(this);
      return () => console.log(this);
   }
}

এটা রান করালেঃ

lex56.aFunc()();

অ্যারো ফাংশনের বাইরের ইএস৫ এর ফাংশনে this ঠিক যা ছিলো, অ্যারো ফাংশনের ভিতরেও সেইম তাই আছে। একেই অ্যারো ফাংশনের লেক্সিক্যাল this কীওয়ার্ড বলে। আর এটা অনেক কাজের। প্রত্যেকবেলা একটা নতুন ফাংশন নিলে আগে যেখানে আমাদের এই this কীওয়ার্ডের ভ্যালু কি হবে সেটা নিয়ে ভাবতে হতো এখন সেটা করতে হবে না। কারণ আমরা জানি অ্যারো ফাংশনের নিজস্ব কোনো প্রভাব নাই this এর উপর।

এখন ইএস৫ এ আমরা this কীওয়ার্ডের ভ্যালু স্পষ্টভাবে বলে দিতে পারতাম call(), bind() অথবা apply() মেথড ইউজ করে। কিন্তু আমরা ইএস৬ এর অ্যারো ফাংশনে এর ভিতরের this এর ভ্যালু এভাবে স্পষ্টভাবে বলে দিতে পারবো না। লেক্সিক্যাল স্কোপিং এর মাধ্যমে এটা এর আশেপাশে থাকা this এর ভ্যালুই ইউজ করবে। এটাকে এক দিক থেকে খারাপ মনে হলেও এটা আসলে অনেক ফ্লেক্সিবল, আস্তে আস্তে ইউজ করতে করতেই দেখবেন।

আমরা চাইলে ইফির সাহায্যে অ্যারো ফাংশন এভাবেও লিখতে পারিঃ

(() => {
   console.log('My name is Zonayed Ahmed');
})();

আজকে এই পর্যন্তই :) আশা করি অ্যারো ফাংশন নিয়ে আর কোনো কনফিউশন থাকবে না…

শেয়ার করুন

লেখাটি ভাল লাগলে সোশ্যাল মিডিয়ায় শেয়ার করুন। আপনার কলিগ, বন্ধু কিংবা প্রিয় কারও কাজে লাগতে পারে। জানেন তো, শেয়ারিং ইজ কেয়ারিং!

সাবস্ক্রিপশন সেন্টার

প্রতিদিন ওয়েবসাইটে আসা আপনার জন্য কষ্টকর হতে পারে। তাই যখনই আমি নতুন ব্লগ পোস্ট, সিরিজ, বই বা ভিডিও পাবলিশ করব,
তখনই তা আপনার ইমেইলে পেতে সাবস্ক্রাইব করুন। নো স্প্যামিং প্রমিজ!