diff --git a/class-overview/Lecture-04/README.md b/class-overview/Lecture-04/README.md index b25a18f..b7c1981 100644 --- a/class-overview/Lecture-04/README.md +++ b/class-overview/Lecture-04/README.md @@ -16,14 +16,14 @@ আমরা জানি ভ্যারিয়েবল মানে চলক। বিগিনারদের একটা সমস্যা হয় যে কোন জায়গায় ভ্যারিয়েবল নিতে হবে আর কোন জায়গায় নিতে হবে না। এর জন্য কিছু ট্রিকস আছে। তার আগে আমাদের জানা দরকার ভ্যারিয়েবলের কাজটা কি? সহজ ভাষায় বলতে গেলে ভ্যারিয়েবল আমাদের যেকোনো কিছু ডায়নামিক করতে সাহায্য করে। এটাই একমাত্র কাজ। এটা ছাড়া ভ্যারিয়েবলের আর কোনো কাজ নেই। এটা অনেকটা পাত্রের মতো। পাত্র যতো বেশি লাগবে জায়গা ততো বেশি লাগবে। মানে বেশি মেমোরি লাগবে। তাহলে এক্সট্রা মেমোরির দরকার কি? ভ্যারিয়েবল কম নিলেই তো হয়। তাহলে আমাদের অ্যাপ্লিকেশন অনেক হালকা হবে। কিন্তু তা সত্ত্বেও আমাদের ভ্যারিয়েবল নিতে হয়। যেমন ধরেন আমরা পানি খাবো। এই পানি কিভাবে আমাদের কাছে আসবে? প্রথমে মাটির নিচ থেকে পানি পাইপ এবং পাম্পের মাধ্যমে বাসার নিচে একটা ট্যাংকে জমা হয়। এরপর আরেকটা পাম্পের মাধ্যমে তা ছাদের উপর গিয়ে আরেকটা ট্যাংকে জমা হয়। ওখানে থেকে পাইপিং এর মাধ্যমে বাসায় বাসায় ডিস্ট্রিবিউট করা হয়। বাসায় ট্যাপের মাধ্যমে সেই পানি আমরা ফিল্টারের মধ্যে জমা করি। ফিল্টার হওয়ার পর সেই পানি আমরা জগ বা বোতলে নিয়ে রাখি। এরপর যখন পানি খাওয়ার প্রয়োজন হয় তখন আমরা জগ বা বোতল থেকে গ্লাসে ঢেলে পানি খাই। আমাদের উদ্দেশ্য কিন্তু পানি খাওয়া তাহলে মাঝখানে এত জায়গায় পানি জমা করে রাখার প্রয়োজন কি? যদি ট্যাংকে জমা রাখতে না পারতাম তাহলে সবার ঘরে ঘরে ডিস্ট্রিবিউট করা সম্ভব হতো না। যদি ফিল্টারে না রাখতাম তাহলে পানি বিশুদ্ধ করতে পারতাম না। সুতরাং ভ্যারিয়েবলও এরকম। এরা ডাটা স্টোর করে রাখে। ভ্যারিয়েবল যদি আমরা না নিই তাহলে আমরা ডাটা দ্বিতীয়বার ইউজ করতে পারতাম না। ```js -console.log('Abu Rayhan', 'Abu Rayhan'.length); // Abu Rayhan 10 +console.log("Abu Rayhan", "Abu Rayhan".length); // Abu Rayhan 10 ``` উপরের উদাহরণে যদি আমরা অন্য কোনো নাম দিয়ে করতে চাই তাহলে সেটা সম্ভব না। সেটা করতে গেলে বর্তমান নামকে বাদ দিতে হবে। কারণ স্ট্যাটিক কোডের ক্ষেত্রে রানটাইমে কোনো কিছু চেইঞ্জ করা যায় না। এখন প্রশ্ন আসতে পারে রানটাইম আর কম্পাইল টাইম কি? ```js -console.log('Abu Rayhan', 'Abu Rayhan'.length); // Abu Rayhan 10 -throw new Error('Something wrong'); // Error +console.log("Abu Rayhan", "Abu Rayhan".length); // Abu Rayhan 10 +throw new Error("Something wrong"); // Error ``` এখানে প্রোগ্রামে কোনো ভুল নেই। কিন্তু প্রোগ্রাম রান করতে গিয়ে দেখা যাচ্ছে একটা এরর আছে। একে বলে রানটাইম এরর। প্রোগ্রাম রান করার সময়কে বলা হচ্ছে রানটাইম। @@ -38,7 +38,7 @@ console.log('Abu Rayhan', 'Abu Rayhan'.length); এখন রানটাইমে আমরা ডায়নামিক্যালি অনেক কিছু চেইঞ্জ করতে পারি। যেমন কিছু ইনপুট দিতে পারি, ইন্টারনেট থেকে কিছু নিয়ে আসতে পারি, মাউস দিয়ে ক্লিক করতে পারি। এসব কিছুই রানটাইমে হয়। কিন্তু যখন আমরা প্রথম উদাহরণের মতো স্ট্যাটিক ডাটা নিয়ে কাজ করবো তখন আমরা কোনোভাবেই লগের ভিতরে থাকা ডাটা চেইঞ্জ করতে পারবো না। এজন্য আমাদের ভ্যারিয়েবল নিতে হবে। যখনই আমরা দেখবো ডাটা তখনই আমরা একটা ভ্যারিয়েবল নিয়ে নিবো। ```js -let name = 'Abu Rayhan'; +let name = "Abu Rayhan"; console.log(name, name.length); // Abu Rayhan 10 ``` @@ -48,23 +48,23 @@ console.log(name, name.length); // Abu Rayhan 10 ```js const names = [ - 'HM Nayeem', - 'Aditya Chakraborty', - 'Abu Rayhan', - 'Shaker Hossain', - 'Akib Ahmad', - 'Alvi Chowdhury', + "HM Nayeem", + "Aditya Chakraborty", + "Abu Rayhan", + "Shaker Hossain", + "Akib Ahmad", + "Alvi Chowdhury", ]; let index = -1; let person = names[++index]; setInterval(() => { - person = names[index++]; - console.log(person, person.length); + person = names[index++]; + console.log(person, person.length); - if (index === names.length) { - index = 0; - } + if (index === names.length) { + index = 0; + } }, 1000); ``` @@ -94,19 +94,19 @@ lessThan(); ```js if (studyBasic) { - wontJoin(); + wontJoin(); } if (studyAdvanced) { - join(); + join(); } if (teacherSpeaks) { - silent(); + silent(); } if (!teacherSpeaks) { - shout(); + shout(); } ``` @@ -118,27 +118,27 @@ if (!teacherSpeaks) { // Scenario 1 - Single branch // if condition if (hasMoney) { - buyPhone(); + buyPhone(); } // Scenario 2 - Two branches // if else condition -if (toss === 'head') { - win(); +if (toss === "head") { + win(); } else { - loss(); + loss(); } // Scenario 3 - Multiple branches // else if let a = 1, - b = 2; + b = 2; if (a > b) { - big(); + big(); } else if (a < b) { - small(); + small(); } else { - same(); + same(); } ``` @@ -155,14 +155,14 @@ if (a > b) { লুপের একটাই কাজ। একই কাজ বারবার করা। যেমন আমাদের একজন ক্লায়েন্ট এসে বললেন বাংলাদেশ তো এবার ৫১ বছরে পা দিলো। আমরা আমাদের অ্যাপ্লিকেশনে এমন কিছু করবো যেন ৫১ বার 'We love Bangladesh' লেখা আসে। আমরা অনেক বুদ্ধিমান আমরা ১ ঘন্টা ধরে গুণে গুণে ৫১ বার `console.log('We love Bangladesh')` লিখে ক্লায়েন্টকে দেখালাম। ক্লায়েন্ট বললো না ভাই ৫১ বার না। যেহেতু ১৯৭১ সালে বাংলাদেশ স্বাধীন হয়েছিল আমরা ১৯৭১ বার চাইছি। এবার আমি ৩ দিন ধরে গুণে গুণে সেই একই কোড লিখে বিধ্বস্ত অবস্থায় ক্লায়েন্টের কাছে নিয়ে দেখালাম। ক্লায়েন্ট বললো, নাহ্‌। এভাবে না। আমরা ৩০ লাখ শহীদকে সম্মান দেখিয়ে ৩০ লক্ষ বার এটা প্রিন্ট করবো এবার আমি বেহুঁশ। আমি গিয়ে রিসার্চ করে দেখলাম জাভাস্ক্রিপ্টে `repeat()` নামক একটি ফাংশন আছে। এবার তো ইজি। ক্লায়েন্ট যতবার চায় ততবার লিখে দিতে পারবো জাস্ট এক লাইন কোড লিখে। আমিও নিচের কোড লিখে ক্লায়েন্টের কাছে খুব গর্ব নিয়ে গেলাম জাস্ট ১০ মিনিটের মধ্যে। ```js -console.log('We love Bangladesh\n'.repeat(3000000)); +console.log("We love Bangladesh\n".repeat(3000000)); ``` আমি তো আকাশে উড়ছি। মনে মনে জাভাস্ক্রিপ্টকে ধন্যবাদ দিচ্ছি এই ফাংশনের জন্য। এবার ক্লায়েন্ট দেখে খুব খুশি হলেন। কিন্তু কিছুক্ষণ পরে বললেন, আচ্ছা ৩০ লক্ষ বার তো প্রিন্ট হলো। ইউজার কিভাবে বুঝবে এটা ৩০ লক্ষ বার হয়েছে। প্রতিটার আগে একটা নাম্বার দিয়ে দিলে বিষয়টা আরো ভাল হয়। এবার তো মাথায় হাত। ডায়নামিক্যালি এত নাম্বার কিভাবে করবো? তার জন্য সহজ সমাধান নিয়ে এসেছে প্রোগ্রামিং ল্যাঙ্গুয়েজ। সেটা হলো লুপ। লুপের মাধ্যমে আমরা সহজেই একই কাজ বারবার করাতে পারি যতবার খুশি। ```js for (let i = 1; i <= 3000000; i++) { - console.log(i, 'We love Bangladesh'); + console.log(i, "We love Bangladesh"); } ``` @@ -187,9 +187,9 @@ While loop দিয়েও আমরা for, do while এর কাজ করত ```js while (true) { - let num = Math.ceil(Math.random() * 100); - console.log(num, 'We love Bangladesh'); - if (num === 71) break; + let num = Math.ceil(Math.random() * 100); + console.log(num, "We love Bangladesh"); + if (num === 71) break; } ``` @@ -201,7 +201,7 @@ Do While দিয়ে আমরা কিন্তু for বা do while এর ```js do { - console.log('It will run at least once'); + console.log("It will run at least once"); } while (false); ``` @@ -212,11 +212,11 @@ do { সবচেয়ে অবহেলিত ডাটা স্ট্রাকচার এবং সবচেয়ে শক্তিশালী ডাটা স্ট্রাকচারের মধ্যে অন্যতম। অ্যারে ব্যবহার করে আমরা অনেক কমপ্লেক্স ডাটা স্ট্রাকচার তৈরি করে ফেলতে পারি। যেমন গ্রাফ, হীপ, স্ট্যাক, কিউ। ২/৩ লক্ষ ডাটা নিয়ে কাজ করার জন্য অ্যারে অনেক পাওয়ারফুল এবং পারফেক্ট ডাটা স্ট্রাকচার। প্রশ্ন হলো অ্যারে কেন আসছে আর অ্যারের কাজ কি? আমরা কয়েকজন মানুষের নাম স্টোর করে রাখতে চাইছি। সেটা আমরা ভ্যারিয়েবল দিয়ে করতে পারি। ```js -const name1 = 'Rayhan'; -const name2 = 'Alvi'; -const name3 = 'Anik'; -const name4 = 'Arjun'; -const name5 = 'Ayman'; +const name1 = "Rayhan"; +const name2 = "Alvi"; +const name3 = "Anik"; +const name4 = "Arjun"; +const name5 = "Ayman"; ``` এখন আমি চাইছি এই নামগুলোকে লোয়ারকেসে কনভার্ট করবো। সেটার জন্য আমাদের প্রত্যেকটা ধরে ধরে কনভার্ট করতে হবে। @@ -232,7 +232,7 @@ console.log(name5, name5.toLowerCase()); এখন এখানে তো ৫টা নাম না থেকে তো ৫ লক্ষ নাম থাকতে পারতো। সেগুলোকে যদি প্রত্যেকটা ধরে ধরে কনভার্ট করতে হয় তাহলে সেটা তো একটা অসম্ভব ব্যাপার। তার জন্য আমাদের এমন একটা উপায় দরকার যাতে করে আমরা সব নামকে একটা ভ্যারিয়েবলের মধ্যে রাখতে পারি। এখন একটা ভ্যারিয়েবলের মধ্যে রেখে দেখি। ```js -const persons = 'Rayhan, Alvi, Anik, Arjun, Ayman'; +const persons = "Rayhan, Alvi, Anik, Arjun, Ayman"; ``` এখন এখানে প্রব্লেম হলো এগুলো সব মিলে একটা বড় স্ট্রিং এ পরিণত হয়ে গেছে। এখানে থেকে আলাদা করবো কিভাবে? আলাদা আলাদা ভাবে স্টোর করে দেখা যাক। @@ -244,13 +244,13 @@ const persons = 'Rayhan', 'Alvi', 'Anik', 'Arjun', 'Ayman'; কিন্তু এখন প্রোগ্রাম রান করাতে গেলে অনেক বড়সড় একটা এরর খেয়ে বসে থাকবো আমরা। এই সমস্যা সমাধানের জন্য আমাদের কাছে একটা ডাটা স্ট্রাকচার আছে যার নামে অ্যারে। কিছু না জাস্ট উপরের উদাহরণের আগে আর পরে `[]` বসিয়ে দিলেই অ্যারে হয়ে যাবে। ```js -const persons = ['Rayhan', 'Alvi', 'Anik', 'Arjun', 'Ayman']; +const persons = ["Rayhan", "Alvi", "Anik", "Arjun", "Ayman"]; ``` এবার এখান থেকে ডাটা কিভাবে বের করা যায়? প্রতিটা অ্যারে এলিমেন্টের পজিশনের একটা নাম্বার আছে। একে বলে ইনডেক্স। ইনডেক্স শুরু হয় ০ থেকে। তাহলে ১ম পজিশনের ইনডেক্স ০, ২য় পজিশনের ইনডেক্স ১, ৩য় পজিশনের ইনডেক্স ২ এভাবে করে ইনডেক্সিং করা যায়। তাহলে আমরা অ্যারের একটা নাম পেলাম আর নাম্বার পেলাম। নাম্বার পাওয়ার কারণে সুবিধা হলো আমরা এখানে সহজেই ক্যালকুলেশন করতে পারবো। আর এটাই অ্যারের পাওয়ার। এখন কিভাবে অ্যারে থেকে ডাটা বের করা যায় সেটা দেখি। ```js -const persons = ['Rayhan', 'Alvi', 'Anik', 'Arjun', 'Ayman']; +const persons = ["Rayhan", "Alvi", "Anik", "Arjun", "Ayman"]; console.log(persons[0]); console.log(persons[1]); console.log(persons[2]); @@ -261,30 +261,30 @@ console.log(persons[4]); এভাবে আমরা সব নাম বের করে আনতে পারি। এখন এখানে দেখা যাচ্ছে সব একই শুধু ইনডেক্সটা ভিন্ন। মানে একই কাজ বারবার চলছে। তাহলে এখানে আমরা একটা লুপ চালাতে পারি। ```js -const persons = ['Rayhan', 'Alvi', 'Anik', 'Arjun', 'Ayman']; +const persons = ["Rayhan", "Alvi", "Anik", "Arjun", "Ayman"]; for (let i = 0; i < 5; i++) { - console.log(persons[i]); + console.log(persons[i]); } ``` এবার যদি প্রোগ্রাম রান করা হয় তাহলে দেখা যাবে সব নাম সুন্দর করে প্রিন্ট হয়ে যাবে। এখানে একটা প্রব্লেম আছে। প্রব্লেমটা বুঝার জন্য আমরা আরো দুইটা নাম অ্যাড করি। ```js -const persons = ['Rayhan', 'Alvi', 'Anik', 'Arjun', 'Ayman', 'Ayuub', 'Bidyut']; +const persons = ["Rayhan", "Alvi", "Anik", "Arjun", "Ayman", "Ayuub", "Bidyut"]; for (let i = 0; i < 5; i++) { - console.log(persons[i]); + console.log(persons[i]); } ``` এখন যদি প্রোগ্রাম চালাই দেখা যাবে `Ayman` পর্যন্ত এসেই লুপ থেমে যাবে। কারণ আমার লুপের রেঞ্জে দেয়া আছে ইনডেক্স ৫ এর কম হতে হবে। এই সমস্যা সমাধানের জন্য আমরা ৫ এর জায়গায় ডায়নামিক্যালি `persons.length` বসিয়ে দিলেই হয়ে যাবে। তাহলে অ্যারের লেংথ যতোই বাড়ুক সে ডায়নামিক্যালি আপডেট হয়ে যাবে। এবার প্রথম উদাহরণটা যদি আমরা অ্যারে এবং লুপ দিয়ে করি তাহলে কেমন দেখাবে? ```js -const persons = ['Rayhan', 'Alvi', 'Anik', 'Arjun', 'Ayman', 'Ayuub', 'Bidyut']; +const persons = ["Rayhan", "Alvi", "Anik", "Arjun", "Ayman", "Ayuub", "Bidyut"]; for (let i = 0; i < 5; i++) { - console.log(students[i], students[i].toLowerCase()); + console.log(students[i], students[i].toLowerCase()); } ``` @@ -298,11 +298,11 @@ const bools = [true, true, false, false]; const nulls = [null, null, null]; const undefineds = [undefined, undefined, undefined]; const arrayOfArray = [ - [1, 2, 3], - [4, 5, 6], - [7, 8, 9], + [1, 2, 3], + [4, 5, 6], + [7, 8, 9], ]; -const mixed = [true, null, 'Str', 5, [12, 2, 4]]; +const mixed = [true, null, "Str", 5, [12, 2, 4]]; ``` এছাড়াও অ্যারেতে অবজেক্ট এবং ফাংশনও স্টোর করা যায়। যেহেতু আমরা এখনও অবজেক্ট ও ফাংশন নিয়ে আলোচনা করিনি তাই আমরা এখানে সেটা দেখালাম না। একটা অ্যারেতে ভিন্ন ডাটা টাইপের ডাটা স্টোর করা গেলেও আমরা একটা অ্যারেতে শুধু একই ডাটা টাইপের ডাটা স্টোর করবো। কারণ হলো ধরেন আপনি ছাত্রছাত্রীর নামের একটা অ্যারে বানালেন। এখন সেখানে যদি আপনি তাদের ঠিকানা, ফোন নাম্বার সব দিয়ে রাখেন তাহলে নাম খুঁজে বের করতে কষ্ট হয়ে যাবে। তাই একটা অ্যারেতে একই টাইপের ডাটা স্টোর করে রাখা উচিৎ। @@ -314,11 +314,11 @@ const mixed = [true, null, 'Str', 5, [12, 2, 4]]; অ্যারেতে আমরা কিছু ছাত্রের নাম লিখলাম। কিন্তু এখন যদি আমরা তাদের ইমেইল, বয়স এবং সে কি বর্তমান ক্লাসে উপস্থিত আছে কিনা সে ইনফরমেশন স্টোর করতে চাই তাহলে অ্যারে দিয়ে করলে একটা প্রব্লেম আছে। কি প্রব্লেম সেটা আমরা একটু দেখার চেষ্টা করি। ```js -const student = ['Abu', 'Rayhan', 'rayhan@example.com', 25, true]; +const student = ["Abu", "Rayhan", "rayhan@example.com", 25, true]; sendEMail(students[0]); function sendEmail(email) { - console.log('Sending Email to ', email); + console.log("Sending Email to ", email); } ``` @@ -326,17 +326,17 @@ function sendEmail(email) { ```js const student = { - firstName: 'Abu', - secondName: 'Rayhan', - email: 'rayhan@example.com', - age: 25, - attend: true, + firstName: "Abu", + secondName: "Rayhan", + email: "rayhan@example.com", + age: 25, + attend: true, }; sendEMail(students.email); function sendEmail(email) { - console.log('Sending Email to ', email); + console.log("Sending Email to ", email); } ``` @@ -346,37 +346,37 @@ function sendEmail(email) { ```js const student1 = { - firstName: 'Abu', - secondName: 'Rayhan', - email: 'rayhan@example.com', - age: 25, - attend: true, + firstName: "Abu", + secondName: "Rayhan", + email: "rayhan@example.com", + age: 25, + attend: true, }; const student2 = { - firstName: 'Alvi', - secondName: 'Chowdhury', - email: 'alvi@example.com', - age: 25, - attend: true, + firstName: "Alvi", + secondName: "Chowdhury", + email: "alvi@example.com", + age: 25, + attend: true, }; const student3 = { - firstName: 'Akib', - secondName: 'Ahmad', - email: 'akib@example.com', - age: 25, - attend: true, + firstName: "Akib", + secondName: "Ahmad", + email: "akib@example.com", + age: 25, + attend: true, }; const allStudents = [student1, student2, student3]; for (let i = 0; i < allStudents.length; i++) { - sendEmail(allStudents[i].email); + sendEmail(allStudents[i].email); } function sendEmail(email) { - console.log('Sending email to', email); + console.log("Sending email to", email); } ``` @@ -390,8 +390,8 @@ function sendEmail(email) { ```js for (let i = 0; i < allStudents.length; i++) { - // sendEmail(allStudents[i].email); - console.log('Sending email to', allStudents[i].email); + // sendEmail(allStudents[i].email); + console.log("Sending email to", allStudents[i].email); } // function sendEmail(email) { @@ -402,9 +402,9 @@ for (let i = 0; i < allStudents.length; i++) { আমরা ফাংশন না লিখেও সেইম কাজ করতে পারতাম। কিন্তু লুপের ভিতরের লাইনটা লুপের বাইরে অন্য কোথাও কাজ করবে না। কিন্তু ফাংশন যেকোনো জায়গায় কল করা যাবে। আবার ধরেন আমার অন্য জায়গায় দরকার পুরো নাম সেটা কি আবার সেই লুপ চালিয়ে করবো। না, আমরা ফাংশন দিয়ে করবো। এক্ষেত্রে আমরা একটা বিল্ড ইন ফাংশন ব্যবহার করে দেখি। ```js -allStudents.forEach((item) => console.log('Email ', item.email)); +allStudents.forEach((item) => console.log("Email ", item.email)); allStudents.forEach((item) => - console.log('Full Name ', item.firstName, item.secondName) + console.log("Full Name ", item.firstName, item.secondName) ); ``` @@ -416,7 +416,7 @@ allStudents.forEach((item) => ```js function nameOfFunction() { - console.log('Hello', 'Elias'); + console.log("Hello", "Elias"); } nameOfFunction(); // Hello Elias @@ -428,11 +428,11 @@ nameOfFunction(); // Hello Elias ```js function nameOfFunction(name) { - console.log('Hello', name); + console.log("Hello", name); } -nameOfFunction('Murshed'); // Hello Murshed -nameOfFunction('Fahim'); // Hello Fahim +nameOfFunction("Murshed"); // Hello Murshed +nameOfFunction("Fahim"); // Hello Fahim nameOfFunction(); // Hello undefined ``` @@ -440,15 +440,15 @@ nameOfFunction(); // Hello undefined ```js function nameOfFunction(name) { - if (!name) { - console.log('Please provide your name'); - } else { - console.log('Hello', name); - } + if (!name) { + console.log("Please provide your name"); + } else { + console.log("Hello", name); + } } -nameOfFunction('Murshed'); // Hello Murshed -nameOfFunction('Fahim'); // Hello Fahim +nameOfFunction("Murshed"); // Hello Murshed +nameOfFunction("Fahim"); // Hello Fahim nameOfFunction(); // Please provide your name ``` @@ -474,8 +474,8 @@ const randomNumber = Math.floor(Math.random() * 1000); ```js function generateRandomNumber(max) { - const randomNumber = Math.floor(Math.random() * max); - return randomNumber; + const randomNumber = Math.floor(Math.random() * max); + return randomNumber; } console.log(generateRandomNumber(10)); @@ -487,14 +487,16 @@ console.log(generateRandomNumber(1000)); ```js function generateRandomNumber(min, max) { - const randomNumber = Math.floor(Math.random() * min + (max - min)); - return randomNumber; + const randomNumber = Math.floor(Math.random() * (max - min + 1)) + min; + return randomNumber; } console.log(generateRandomNumber(5, 10)); console.log(generateRandomNumber(85, 100)); ``` +এখানে ফাংশনটি সর্বচ্ছ max - min + 1 পর্যন্ত রেনডম নাম্বার দেখায় সাথে min যোগ করায় min এ উপরের সংখ্যা গুলোকে দেখায় । + তাহলে বুঝুন ফাংশন আমাদের কাজকে কতটা সহজ করে দেয়। ## Expression vs Statement @@ -502,20 +504,20 @@ console.log(generateRandomNumber(85, 100)); এই বিষয় বুঝার আগে আমরা একটু কিছু উদাহরণ দেখি ```js -const name1 = 'Rayhan'; // Statement -const name2 = 'Alvi'; // Statement -const name3 = 'Anik'; // Statement -const name4 = 'Arjun'; // Statement -const name5 = 'Ayman'; // Statement +const name1 = "Rayhan"; // Statement +const name2 = "Alvi"; // Statement +const name3 = "Anik"; // Statement +const name4 = "Arjun"; // Statement +const name5 = "Ayman"; // Statement const students = [ - 'Rayhan', - 'Alvi', - 'Anik', - 'Arjun', - 'Ayman', - 'Ayuub', - 'Bidyut', + "Rayhan", + "Alvi", + "Anik", + "Arjun", + "Ayman", + "Ayuub", + "Bidyut", ]; // Statement console.log(students[0]); // Expression @@ -525,7 +527,7 @@ console.log(students[3]); // Expression console.log(students[4]); // Expression for (let i = 0; i < students.length; i++) { - console.log(students[i], students[i].toLowerCase()); // Expression + console.log(students[i], students[i].toLowerCase()); // Expression } // Statement name1.sendEmail(); // Expression @@ -539,66 +541,66 @@ const bools = [true, true, false, false]; // Statement const nulls = [null, null, null]; // Statement const undefineds = [undefined, undefined, undefined]; // Statement const arrayOfArray = [ - [1, 2, 3], - [4, 5, 6], - [7, 8, 9], + [1, 2, 3], + [4, 5, 6], + [7, 8, 9], ]; // Statement -const mixed = [true, null, 'Str', 5, [12, 2, 4]]; // Statement +const mixed = [true, null, "Str", 5, [12, 2, 4]]; // Statement const student1 = { - firstName: 'Abu', - secondName: 'Rayhan', - email: 'rayhan@example.com', - age: 25, - attend: true, + firstName: "Abu", + secondName: "Rayhan", + email: "rayhan@example.com", + age: 25, + attend: true, }; // Statement const student2 = { - firstName: 'Alvi', - secondName: 'Chowdhury', - email: 'alvi@example.com', - age: 25, - attend: true, + firstName: "Alvi", + secondName: "Chowdhury", + email: "alvi@example.com", + age: 25, + attend: true, }; // Statement const student3 = { - firstName: 'Akib', - secondName: 'Ahmad', - email: 'akib@example.com', - age: 25, - attend: true, + firstName: "Akib", + secondName: "Ahmad", + email: "akib@example.com", + age: 25, + attend: true, }; // Statement const allStudents = [student1, student2, student3]; // Statement for (let i = 0; i < allStudents.length; i++) { - sendMail(allStudents[i].email); // Expression + sendMail(allStudents[i].email); // Expression } // Statement function sendMail(email) { - console.log('Sending email to', email); + console.log("Sending email to", email); } // Statement -allStudents.forEach((item) => console.log('Email ', item.email)); // Expression +allStudents.forEach((item) => console.log("Email ", item.email)); // Expression allStudents.forEach((item) => - console.log('Full Name ', item.firstName, item.secondName) + console.log("Full Name ", item.firstName, item.secondName) ); // Expression function nameOfFunction(name) { - if (!name) { - console.log('Please provide your name'); - } else { - console.log('Hello', name); - } + if (!name) { + console.log("Please provide your name"); + } else { + console.log("Hello", name); + } } // Statement -nameOfFunction('Murshed'); // Expression -nameOfFunction('Fahim'); // Expression +nameOfFunction("Murshed"); // Expression +nameOfFunction("Fahim"); // Expression nameOfFunction(); // Expression function generateRandomNumber(min = 1, max) { - const randomNumber = Math.floor(Math.random() * min + (max - min)); // Statement - return randomNumber; // Expression + const randomNumber = Math.floor(Math.random() * min + (max - min)); // Statement + return randomNumber; // Expression } // Statement console.log(generateRandomNumber(5, 10)); // Expression diff --git a/class-overview/Lecture-05-06/README.md b/class-overview/Lecture-05-06/README.md index d3035b9..351b3a9 100644 --- a/class-overview/Lecture-05-06/README.md +++ b/class-overview/Lecture-05-06/README.md @@ -57,7 +57,7 @@ const numbers = [2, 5, 6, 7, 89, 100]; for (let i = 0; i < numbers.length; i++) { - console.log(numbers[i]); + console.log(numbers[i]); } ``` @@ -67,7 +67,7 @@ for (let i = 0; i < numbers.length; i++) { const numbers = [2, 5, 6, 7, 89, 100]; for (let i = 0; i < numbers.length; i++) { - console.log(numbers[i] * 2); + console.log(numbers[i] * 2); } ``` @@ -78,7 +78,7 @@ const numbers = [2, 5, 6, 7, 89, 100]; let sum = 0; for (let i = 0; i < numbers.length; i++) { - sum += numbers[i]; + sum += numbers[i]; } console.log(sum); @@ -94,7 +94,7 @@ console.log(sum); const numbers = [2, 5, 6, 7, 89, 100]; numbers.forEach(function () { - console.log('Hello World'); + console.log("Hello World"); }); ``` @@ -104,7 +104,7 @@ numbers.forEach(function () { const numbers = [2, 5, 6, 7, 89, 100]; numbers.forEach(function () { - console.log(arguments); + console.log(arguments); }); /* * Output @@ -123,7 +123,7 @@ numbers.forEach(function () { const numbers = [2, 5, 6, 7, 89, 100]; numbers.forEach(function (value, index, array) { - console.log(value, index, array); + console.log(value, index, array); }); /* * Output @@ -138,6 +138,8 @@ numbers.forEach(function (value, index, array) { দেখা যাচ্ছে আমরা যে আউটপুট পেয়েছিলাম আর্গুমেন্টস এর বেলায় ঠিক সেই আউটপুটই পেয়েছি। `arguments` অনেক কাজের। আপনি যখন কোনো লাইব্রেরি বা ফ্রেমওয়ার্ক নিয়ে কাজ করবেন তখন যদি কোনো মেথডের আর্গুমেন্ট জানার প্রয়োজন হয় সহজেই তা বের করে নিতে পারবেন। +**arguments:** এটি একটি জাভাস্ক্রিপ্টের একটি বিশেষ ধরনের অবজেক্ট। যখন আপনি কোনো ফাংশন কল করেন, তখন সেই ফাংশনের ভিতরে arguments নামে একটি অবজেক্ট তৈরি হয়। এই অবজেক্টে ফাংশনকে পাস করা সকল আর্গুমেন্টের একটি তালিকা থাকে। + এবার আসি আবার `forEach` এর কথায়। এটা দিয়ে ফর লুপের যাবতীয় যা যা কাজ আমরা করি সবই করতে পারি। এবার আমরা ফর লুপ দিয়ে যোগফলের যে কাজটি করেছিলাম সেটা একটু `forEach` দিয়ে করে দেখি। ```js @@ -145,7 +147,7 @@ const numbers = [2, 5, 6, 7, 89, 100]; let sum = 0; numbers.forEach(function (value) { - sum += value; + sum += value; }); console.log(sum); // 209 ``` @@ -156,9 +158,9 @@ console.log(sum); // 209 const numbers = [2, 5, 6, 7, 89, 100]; numbers.forEach(function (value) { - if (value % 2 === 0) { - console.log(value); - } + if (value % 2 === 0) { + console.log(value); + } }); ``` @@ -171,9 +173,9 @@ const numbers = [2, 5, 6, 7, 89, 100]; let sum = 0; numbers.forEach(function (value, index) { - if (index <= 3) { - sum += value; - } + if (index <= 3) { + sum += value; + } }); console.log(sum); ``` @@ -183,7 +185,7 @@ console.log(sum); ধরি আমাদের একটা অ্যারে আছে নিচের মতো। ```js -const arr = [1, 2, 3, null, false, 4, 5, '', 'test', 6, 7]; +const arr = [1, 2, 3, null, false, 4, 5, "", "test", 6, 7]; ``` এখন আমরা চাইছি এখান থেকে নাম্বার ছাড়া বাকি যা আছে সেগুলো বাদ দিয়ে শুধু নাম্বারগুলো ফিল্টার করে নিতে। সেটা আমরা ডিক্লারেটিভ ওয়েতে করতে চাইছি না। আমরা চাইছি ইম্পেরেটিভ ওয়েতে করতে। কিভাবে করতে পারি? @@ -191,12 +193,12 @@ const arr = [1, 2, 3, null, false, 4, 5, '', 'test', 6, 7]; আমরা এভাবে শুরু করতে পারি। ```js -const arr = [1, 2, 3, null, false, 4, 5, '', 'test', 6, 7]; +const arr = [1, 2, 3, null, false, 4, 5, "", "test", 6, 7]; for (let i = 0; i < arr.length; i++) { - if (typeof arr[i] !== 'number') { - arr[i] = undefined; - } + if (typeof arr[i] !== "number") { + arr[i] = undefined; + } } console.log(arr); // [1, 2, 3, undefined, undefined, 4, 5, undefined, undefined, 6, 7]; @@ -214,37 +216,56 @@ console.log(arr); // [1, 2, 3, undefined, undefined, 4, 5, undefined, undefined, এবার আমাদের আইডিয়াকে আমরা একটু কোডে রূপান্তরিত করে দেখি। ```js -const arr = [1, 2, 3, null, false, 4, 5, '', 'test', 6, 7]; +const arr = [1, 2, 3, null, false, 4, 5, "", "test", 6, 7]; for (let i = 0; i < arr.length; i++) { - for (let j = i; j < arr.length - 1; j++) { - if (!arr[j] || typeof arr[j] !== 'number') { - arr[j] = arr[j + 1]; - arr[j + 1] = undefined; - } - } + for (let j = i; j < arr.length - 1; j++) { + if (!arr[j] || typeof arr[j] !== "number") { + arr[j] = arr[j + 1]; + arr[j + 1] = undefined; + } + } } console.log(arr); // [1, 2, 3, 4, 5, 6, 7, undefined, undefined, undefined, undefined]; ``` +### কাজটি সহজ করে এভাবে ভেঙে ভেঙে ও করা যেতে পারে। + +```js +let index = 0; + +for (let i = 0; i < arr.length; i++) { + if (typeof arr[i] === "number") { + arr[index] = arr[i]; // বৈধ সংখ্যা হলে সামনের দিকে সরাও + index++; + } +} + +// বাকি অংশ `undefined` দিয়ে পূরণ করো +for (let i = index; i < arr.length; i++) { + arr[i] = undefined; +} +console.log(arr); +``` + আমরা তাহলে আমাদের স্টেপ ৪ পেয়ে গেলাম। এবার এখান থেকে `undefined` বাদ দিয়ে দিতে হবে। সেটার জন্য আমরা একটা কাজ করতে পারি। ```js -const arr = [1, 2, 3, null, false, 4, 5, '', 'test', 6, 7]; +const arr = [1, 2, 3, null, false, 4, 5, "", "test", 6, 7]; count = 0; for (let i = 0; i < arr.length; i++) { - for (let j = i; j < arr.length - 1; j++) { - if (!arr[j] || typeof arr[j] !== 'number') { - arr[j] = arr[j + 1]; - arr[j + 1] = undefined; - } - } - - if (arr[i] == undefined) { - count++; - } + for (let j = i; j < arr.length - 1; j++) { + if (!arr[j] || typeof arr[j] !== "number") { + arr[j] = arr[j + 1]; + arr[j + 1] = undefined; + } + } + + if (arr[i] == undefined) { + count++; + } } arr.length -= count; @@ -284,22 +305,22 @@ After completion of loop the array looks like this [1, 2, 3, undefined, undefine এখন যদি এই কাজটা ইম্পেরেটিভ ওয়েতে না করে ডিক্লারেটিভ ওয়েতে করতাম তাহলে অনেক সহজে করতে পারতাম। ```js -const arr = [1, 2, 3, null, false, 4, 5, '', 'test', 6, 7]; +const arr = [1, 2, 3, null, false, 4, 5, "", "test", 6, 7]; -const filteredArray = arr.filter((val) => typeof val === 'number'); +const filteredArray = arr.filter((val) => typeof val === "number"); console.log(filteredArray); ``` কিন্তু এই জায়গায় একটা সমস্যা আছে। কারণ `filter` মেথড বিহাইন্ড দ্য সীন একটা এক্সট্রা মেমোরি ব্যবহার করে। আমরা যখন ফ্রন্টএন্ড ডেভেলপমেন্ট করি তখন সাধারণত এতো জটিল ইম্পেরেটিভ ওয়েতে করি না। আমরা যে বিল্ট-ইন মেথড আছে সেগুলো ব্যবহার করি। তাই দেখা যায় যে অনেক সময় ডাটা যখন অনেক বেশি হবে তখন অ্যাপ্লিকেশন হ্যাং হয়ে যায়। এখন আমরা কি সবসময় ইম্পেরেটিভ মেথডেই কাজ করবো? বা কখন বুঝবো আমাকে ইম্পেরেটিভ ওয়েতে করতে হবে, কখন ডিক্লারেটিভ ওয়েতে? প্রথম কথা হচ্ছে ৯০-৯৫% সময়ই আমাদের বিল্ট-ইন মেথড ইউজ করে কাজ হয়ে যাবে। কিন্তু কিছু কিছু ক্ষেত্রে আমাদের অ্যাপ্লিকেশনের কমপ্লেক্সিটি এতো বেশি হয় সেসব ক্ষেত্রে আমাদের বিল্ট-ইন মেথডের বাইরে গিয়ে কাজ করতে হতে পারে। ধরেন আমাদের অ্যারেতে এখন জাস্ট নাম্বার, স্ট্রিং এসব ডাটা আছে। কিন্তু যদি এমন হয় যে প্রতিটি ইলেমেন্ট এক একটা জায়ান্ট অবজেক্ট এবং প্রতিটা অবজেক্টের সাইজ প্রায় এক এমবি করে (যদিও এক এমবি ডাটা বানানো অনেক কঠিন, তাও বুঝার সুবিধার্থে উদাহরণ দিচ্ছি), এরকম যদি ১০০ টা অবজেক্ট থাকে তাহলে মোট অ্যারের সাইজ হবে ১০০ এমবি। এখন যদি এই ১০০ এমবি ডাটার অপারেশনের জন্য আমার আরো ১০০ এমবি মেমোরি খরচ হয় তাহলে সেটা অনেক সমস্যা। তাই এই ক্ষেত্রে আমাদের সম্পূর্ণ ইম্পেরেটিভ ওয়েতে গিয়ে কাজ করতে হবে। যদি আমাদের এখানে মেমোরি কনস্ট্রেইন না থাকতো তাহলে আমরা ইম্পেরেটিভ ওয়েতেও অনেক সহজে এই কাজটা করতে পারতাম। ```jsx -const arr = [1, 2, 3, null, false, 4, 5, '', 'test', 6, 7]; +const arr = [1, 2, 3, null, false, 4, 5, "", "test", 6, 7]; const newArr = []; for (let i = 0; i < arr.length; i++) { - if (typeof arr[i] === 'number') { - newArr.push(arr[i]); - } + if (typeof arr[i] === "number") { + newArr.push(arr[i]); + } } console.log(newArr); ``` @@ -324,11 +345,11 @@ console.log(arr); // [1, 2, 3, 300, 5] ```js const arr = [ - { id: 1, value: 10 }, - { id: 2, value: 20 }, - { id: 3, value: 30 }, - { id: 4, value: 40 }, - { id: 5, value: 50 }, + { id: 1, value: 10 }, + { id: 2, value: 20 }, + { id: 3, value: 30 }, + { id: 4, value: 40 }, + { id: 5, value: 50 }, ]; const index = arr.findIndex((item) => item.id === 4); @@ -349,11 +370,11 @@ console.log(arr); ```js const arr = [ - { id: 1, value: 10 }, - { id: 2, value: 20 }, - { id: 3, value: 30 }, - { id: 4, value: 40 }, - { id: 5, value: 50 }, + { id: 1, value: 10 }, + { id: 2, value: 20 }, + { id: 3, value: 30 }, + { id: 4, value: 40 }, + { id: 5, value: 50 }, ]; const obj = arr.find((val) => val.id === 4); @@ -379,11 +400,11 @@ console.log(arr); ```js const arr = [ - { id: 1, value: 10 }, - { id: 2, value: 20 }, - { id: 3, value: 30 }, - { id: 4, value: 40 }, - { id: 5, value: 50 }, + { id: 1, value: 10 }, + { id: 2, value: 20 }, + { id: 3, value: 30 }, + { id: 4, value: 40 }, + { id: 5, value: 50 }, ]; const obj = arr.find((val) => val.id === 4); @@ -406,11 +427,11 @@ console.log(a === b); // false ```js const arr = [ - { id: 1, value: 10 }, - { id: 2, value: 20 }, - { id: 3, value: 30 }, - { id: 4, value: 40 }, - { id: 5, value: 50 }, + { id: 1, value: 10 }, + { id: 2, value: 20 }, + { id: 3, value: 30 }, + { id: 4, value: 40 }, + { id: 5, value: 50 }, ]; const index = arr.findIndex((item) => item.id === 4); @@ -430,11 +451,11 @@ console.log(arr); ```js const arr = [ - { id: 1, value: 10 }, - { id: 2, value: 20 }, - { id: 3, value: 30 }, - { id: 4, value: 40 }, - { id: 5, value: 50 }, + { id: 1, value: 10 }, + { id: 2, value: 20 }, + { id: 3, value: 30 }, + { id: 4, value: 40 }, + { id: 5, value: 50 }, ]; const arr2 = arr.filter((item) => item.id !== 4); @@ -483,7 +504,7 @@ console.log(strs); ফিল্টারের কাজ আমরা একটা অ্যারে থেকে যে যে ডাটা চাইছি তা ফিল্টার করে দেয়া। ধরেন আমাদের কাছে একটা অ্যারে আছে। ```js -const numbers = [1, 2, 3, 4, false, '', NaN, 5, 6]; +const numbers = [1, 2, 3, 4, false, "", NaN, 5, 6]; ``` আমরা চাইছি এখান থেকে সমস্ত falsy value বাদ দিয়ে শুধু truthy ভ্যালু নিবো। সেক্ষেত্রে ফিল্টার মেথড আমাদের ব্যবহার করতে হবে। @@ -500,7 +521,7 @@ console.log(filteredArr); আমরা একটু নিচের উদাহরণটা দেখি। ```js -const numbers = [1, 2, 3, 4, false, '', NaN, 5, 6]; +const numbers = [1, 2, 3, 4, false, "", NaN, 5, 6]; const filteredArr = numbers.filter((v) => v); const strs = filteredArr.map((v) => v.toString()); console.log(strs); @@ -509,7 +530,7 @@ console.log(strs); এক্ষেত্রে কিছু অসুবিধা আছে। যখন ফিল্টার হচ্ছে তখন n সংখ্যকবার সে ট্রাভার্স হচ্ছে। আবার যখন ম্যাপ হচ্ছে তখনও আবার ট্রাভার্স হচ্ছে। এতে করে টাইম কমপ্লেক্সিটি বেড়ে যাচ্ছে। এটা চেইন করেও করা যায়। ```js -const numbers = [1, 2, 3, 4, false, '', NaN, 5, 6]; +const numbers = [1, 2, 3, 4, false, "", NaN, 5, 6]; const filteredArr = numbers.filter((v) => v).map((v) => v.toString()); console.log(strs); ``` @@ -530,18 +551,18 @@ console.log(sum); ```js numbers.reduce((acc, cur) => { - return acc; -}, ''); + return acc; +}, ""); ``` প্রথম প্যারামিটার হিসেবে আমরা দিয়েছি acc (accumulator / previous value) এবং দ্বিতীয় ভ্যালু হিসেবে দিয়েছি cur (current value)। acc, cur এর পর আমরা চাইলে ইনডেক্স দিতে পারি, চাইলে পুরো অ্যারে দিতে পারি কিন্তু আমাদের সেটা দরকার নেই। reduce মেথডের সুবিধা হলো এখানে আমরা একটা ইনিশিয়াল ভ্যালু প্রোভাইড করতে পারি। '' এর জায়গায় খালি অবজেক্ট {}, খালি অ্যারে [], শূন্য যেকোনো কিছু বসাতে পারি। সেটা আমরা কি চাইছি তার উপর নির্ভর করবে। এর মানে হলো বর্তমানে acc এর ভ্যালু ঐ ইনিশিয়ালাইজার হিসেবে যেটা দিবো সেটা। দিন শেষে আমরা আমাদের acc কে রিটার্ন করবো। যাই করি না কেন আমরা reduce মেথডে acc কেই রিটার্ন করবো। এখন আমরা চাইছি `const numbers = [1, 2, 3, 4, false, '', NaN, 5, 6];` এটা থেকে আমরা `1234falseNaN56` রিটার্ন করতে। সেটা করতে আমরা reduce মেথডের সাহায্য নিবো। ```js -const numbers = [1, 2, 3, 4, false, '', NaN, 5, 6]; +const numbers = [1, 2, 3, 4, false, "", NaN, 5, 6]; const result = numbers.reduce((acc, cur) => { - acc += cur.toString(); - return acc; -}, ''); + acc += cur.toString(); + return acc; +}, ""); console.log(result); // 1234falseNaN56 ``` @@ -551,13 +572,13 @@ console.log(result); // 1234falseNaN56 এখন আমরা চাইছি এই অ্যারে থেকে শুধু truthy values নিবো। কোনো falsy ভ্যালু নিবো না। সেক্ষেত্রে আমরা একটা কন্ডিশন বসিয়ে দিতে পারি। ```js -const numbers = [1, 2, 3, 4, false, '', NaN, 5, 6]; +const numbers = [1, 2, 3, 4, false, "", NaN, 5, 6]; const result = numbers.reduce((acc, cur) => { - if (cur) { - acc += cur.toString(); - } - return acc; -}, ''); + if (cur) { + acc += cur.toString(); + } + return acc; +}, ""); console.log(result); // 123456 ``` @@ -565,13 +586,13 @@ console.log(result); // 123456 আমরা যদি চাই প্রতিটার শেষে কমা (,) যোগ করবো সেটাও করতে পারি। ```js -const numbers = [1, 2, 3, 4, false, '', NaN, 5, 6]; +const numbers = [1, 2, 3, 4, false, "", NaN, 5, 6]; const result = numbers.reduce((acc, cur, index) => { - if (cur) { - acc += cur.toString() + (index < numbers.length - 1 ? ', ' : ''); - } - return acc; -}, ''); + if (cur) { + acc += cur.toString() + (index < numbers.length - 1 ? ", " : ""); + } + return acc; +}, ""); console.log(result); // 1, 2, 3, 4, 5, 6 ``` @@ -579,31 +600,31 @@ console.log(result); // 1, 2, 3, 4, 5, 6 আমরা চাইলে অ্যারের একটা শেইপও দিতে পারি। যেমন ```js -const numbers = [1, 2, 3, 4, false, '', NaN, 5, 6]; +const numbers = [1, 2, 3, 4, false, "", NaN, 5, 6]; const result = numbers.reduce((acc, cur, i) => { - if (i === 0) { - acc += '['; - } - if (cur) { - acc += cur.toString() + (i < numbers.length - 1 ? ', ' : ''); - } - if (i === numbers.length - 1) { - acc += ']'; - } - return acc; -}, ''); + if (i === 0) { + acc += "["; + } + if (cur) { + acc += cur.toString() + (i < numbers.length - 1 ? ", " : ""); + } + if (i === numbers.length - 1) { + acc += "]"; + } + return acc; +}, ""); console.log(result); // [1, 2, 3, 4, 5, 6] ``` তাহলে আমরা reduce এর পাওয়ারটা বুঝতে পারছি কিছুটা। এটা গেলো এক ধরণের পাওয়ার। আরো অনেক পাওয়ার আছে reduce মেথডের। যেমন এখন আমরা acc স্ট্রিং হিসেবে চাইছি না। আমরা চাইছি সকল truthy ভ্যালুর একটা অ্যারে। সেটাও reduce দিয়ে করা যায়। ```js -const numbers = [1, 2, 3, 4, false, '', NaN, 5, 6]; +const numbers = [1, 2, 3, 4, false, "", NaN, 5, 6]; const result = numbers.reduce((acc, cur) => { - if (cur) { - acc.push(cur.toString()); - } - return acc; + if (cur) { + acc.push(cur.toString()); + } + return acc; }, []); console.log(result); // [ '1', '2', '3', '4', '5', '6' ] ``` @@ -615,32 +636,32 @@ console.log(result); // [ '1', '2', '3', '4', '5', '6' ] ```js const arr = []; for (let i = 1; i < 5000000; i++) { - arr.push(i); + arr.push(i); } -console.time('not-optimized'); +console.time("not-optimized"); arr.filter((item) => item % 2 === 0).map((item) => item * 2); -console.timeEnd('not-optimized'); // not-optimized: 325.853ms +console.timeEnd("not-optimized"); // not-optimized: 325.853ms -console.time('optimized'); +console.time("optimized"); arr.reduce((acc, cur) => { - if (cur % 2 === 0) { - acc.push(cur * 2); - } - return acc; + if (cur % 2 === 0) { + acc.push(cur * 2); + } + return acc; }, []); -console.timeEnd('optimized'); // optimized: 198.256ms +console.timeEnd("optimized"); // optimized: 198.256ms ``` তাহলে দেখা যাচ্ছে reduce method অনেক অপটিমাইজড। এবার আমরা একটু reduce মেথডের ইমপ্লিমেন্টেশনটা দেখি। আমরা আমদের reduce ফুঞ্চতিওন বানিয়ে ফেলতে পারি। যেহেতু আমরা প্রোটোটাইপ নিয়ে আলোচনা করিনি তাই মেথড বানাবো না। আমরা জাস্ট একটা ফাংশন বানাবো। ```js function myReduce(arr, cb, init) { - let acc = init; - for (let i = 0; i < arr.length; i++) { - acc = cb(acc, arr[i], i, arr); - } - return acc; + let acc = init; + for (let i = 0; i < arr.length; i++) { + acc = cb(acc, arr[i], i, arr); + } + return acc; } ``` @@ -650,16 +671,16 @@ function myReduce(arr, cb, init) { const sum = myReduce([1, 2, 3, 4], (a, b) => a + b, 0); console.log(sum); // 10 -const arr = [1, 2, '', false, 3, NaN, false, 4, 5, NaN, 6]; +const arr = [1, 2, "", false, 3, NaN, false, 4, 5, NaN, 6]; const result = myReduce( - arr, - (acc, cur) => { - if (cur) { - acc.push(cur ** 2); - } - return acc; - }, - [] + arr, + (acc, cur) => { + if (cur) { + acc.push(cur ** 2); + } + return acc; + }, + [] ); console.log(result); // [1, 4, 9, 16, 25, 36] ``` @@ -669,24 +690,24 @@ How amazing is this! জাভাস্ক্রিপ্টের যতোই আমরা আরেকটা উদাহরণ দেখি reduce এর। তার জন্য আমাদের axios প্যাকেজটা ইনস্টল করে নেয়া লাগবে। আমরা ইনস্টল করে নিলাম। এখন আমরা [json placeholder](https://jsonplaceholder.typicode.com/posts) এই সাইটে ঢুকলে কিছু ডামী ডাটা পাবো পোস্টের। খেয়াল করলে দেখবো এই ডাটা দেয়া আছে অ্যারে হিসেবে। কিন্তু আমার ট্রাভার্সের চেয়ে গুরুত্বপূর্ণ হলো আপডেট ও ডিলিট করা। ব্যাকএন্ড ডেভেলপার তার সুবিধামতো অ্যারেতে দিয়ে দিলেও আমাদের নিজেদের প্রয়োজনে তা অবজেক্টে রূপান্তরিত করে নেয়া লাগবে। এখানে আমাদের body প্রোপার্টিজ প্রয়োজন নেই। আমাদের দরকার userId, id ও title। আর আমার এতো ডাটার প্রয়োজন নেই আমাদের প্রথম ১০টা ডাটা হলেই হয়ে যাবে। চলুন দেখি। ```js -const axios = require('axios').default; -const url = 'https://jsonplaceholder.typicode.com/posts'; +const axios = require("axios").default; +const url = "https://jsonplaceholder.typicode.com/posts"; async function getData() { - const { data } = await axios.get(url); - const result = data.slice(0, 10).map((item) => { - return { - userId: item.userId, - id: item.id, - title: item.title, - }; - }); - return result; + const { data } = await axios.get(url); + const result = data.slice(0, 10).map((item) => { + return { + userId: item.userId, + id: item.id, + title: item.title, + }; + }); + return result; } getData() - .then((data) => console.log(data)) - .catch((e) => console.log(e)); + .then((data) => console.log(data)) + .catch((e) => console.log(e)); /* [ @@ -720,24 +741,24 @@ getData() আমরা map ব্যবহার করে প্রথম ১০টি ডাটা পেয়ে গেলাম। এবং বডিও আমরা বাদ দিয়ে দিলাম। কিন্তু এখনও এটা অ্যারে রিটার্ন করছে। map করলে কখনও আমরা অবজেক্ট রিটার্ন করতে পারবো না। কারণ map সবসময় অ্যারেই রিটার্ন করে। এবার আমরা একটু reduce নিয়ে কাজ করি। কারণ reduce এ আমরা কি টাইপের ডাটা চাই তা ইনিশিয়ালাইজের মাধ্যমে দিয়ে দিতে পারি। ```js -const axios = require('axios').default; -const url = 'https://jsonplaceholder.typicode.com/posts'; +const axios = require("axios").default; +const url = "https://jsonplaceholder.typicode.com/posts"; async function getData() { - const { data } = await axios.get(url); - const result = data.slice(0, 10).reduce((acc, cur) => { - acc[cur.id] = { - ...cur, - }; - delete acc[cur.id].body; - return acc; - }, {}); - return result; + const { data } = await axios.get(url); + const result = data.slice(0, 10).reduce((acc, cur) => { + acc[cur.id] = { + ...cur, + }; + delete acc[cur.id].body; + return acc; + }, {}); + return result; } getData() - .then((data) => console.log(data)) - .catch((e) => console.log(e)); + .then((data) => console.log(data)) + .catch((e) => console.log(e)); /* { @@ -773,22 +794,22 @@ getData() ```js const names = [ - 'Ayman', - 'Abu Rayhan', - 'Anik', - 'Elias Emon', - 'Engr. Sabbir', - 'Fahim Faisal', - 'Feroz Khan', - 'Habib', - 'HM Azizul', - 'Hridoy Saha', - 'Jahid Hassan', - 'Johir', - 'Md Al-Amin', - 'Md Arafatul', - 'Md Ashraful', - 'Parvez', + "Ayman", + "Abu Rayhan", + "Anik", + "Elias Emon", + "Engr. Sabbir", + "Fahim Faisal", + "Feroz Khan", + "Habib", + "HM Azizul", + "Hridoy Saha", + "Jahid Hassan", + "Johir", + "Md Al-Amin", + "Md Arafatul", + "Md Ashraful", + "Parvez", ]; ``` @@ -830,9 +851,9 @@ Parvez ```js const namesGroup = { - A: ['Ayman', 'Abu Rayhan', 'Anik'], - E: ['Elias Emon', 'Engr. Sabbir'], - F: ['Fahim Faisal', 'Feroz Khan'], + A: ["Ayman", "Abu Rayhan", "Anik"], + E: ["Elias Emon", "Engr. Sabbir"], + F: ["Fahim Faisal", "Feroz Khan"], }; ``` @@ -840,13 +861,13 @@ const namesGroup = { ```js const namesGrouped = names.reduce((acc, cur) => { - const firstLetter = cur[0].toUpperCase(); - if (firstLetter in acc) { - acc[firstLetter].push(cur); - } else { - acc[firstLetter] = [cur]; - } - return acc; + const firstLetter = cur[0].toUpperCase(); + if (firstLetter in acc) { + acc[firstLetter].push(cur); + } else { + acc[firstLetter] = [cur]; + } + return acc; }, {}); console.log(namesGrouped); @@ -867,9 +888,9 @@ console.log(namesGrouped); ```js Object.keys(namesGrouped).forEach((groupKey) => { - console.log('-----------', groupKey, '-----------'); - namesGrouped[groupKey].forEach((name) => console.log(name)); - console.log(); + console.log("-----------", groupKey, "-----------"); + namesGrouped[groupKey].forEach((name) => console.log(name)); + console.log(); }); ``` @@ -885,16 +906,16 @@ Object.keys(namesGrouped).forEach((groupKey) => { ```js const microphone = { - brand: 'Fifine', - indictor: true, - price: 8000, - color: 'Black', - startRecording() { - console.log('recording started'); - }, - stopRecording() { - console.log('recording stopped'); - }, + brand: "Fifine", + indictor: true, + price: 8000, + color: "Black", + startRecording() { + console.log("recording started"); + }, + stopRecording() { + console.log("recording stopped"); + }, }; ``` @@ -913,7 +934,7 @@ const microphone = { ```js const testObj = new Object(); -testObj.name = 'Test Object'; +testObj.name = "Test Object"; testObj.time = new Date(); console.log(testObj); // { name: 'Test Object', time: 2022-06-16T07:09:01.373Z } ``` @@ -928,19 +949,19 @@ console.log(testObj); // { name: 'Test Object', time: 2022-06-16T07:09:01.373Z } ```js const microphone = { - brand: 'Fifine', - indictor: true, - price: 8000, - color: 'Black', - startRecording() { - console.log('recording started'); - }, - stopRecording() { - console.log('recording stopped'); - }, + brand: "Fifine", + indictor: true, + price: 8000, + color: "Black", + startRecording() { + console.log("recording started"); + }, + stopRecording() { + console.log("recording stopped"); + }, }; -microphone.newProperty = 'New Property'; +microphone.newProperty = "New Property"; console.log(microphone); /* { brand: 'Fifine', @@ -957,20 +978,20 @@ console.log(microphone); ```js const microphone = { - brand: 'Fifine', - indictor: true, - price: 8000, - color: 'Black', - startRecording() { - console.log('recording started'); - }, - stopRecording() { - console.log('recording stopped'); - }, + brand: "Fifine", + indictor: true, + price: 8000, + color: "Black", + startRecording() { + console.log("recording started"); + }, + stopRecording() { + console.log("recording stopped"); + }, }; Object.freeze(microphone); -microphone.newProperty = 'New Property'; +microphone.newProperty = "New Property"; console.log(microphone); /* { brand: 'Fifine', @@ -1004,7 +1025,7 @@ console.log(Object.values(microphone)); ```js for (let k in microphone) { - console.log(k, microphone[k]); + console.log(k, microphone[k]); } /* @@ -1068,10 +1089,10 @@ console.log(Object.entries(microphone)); ```js const arr = [ - ['brand', 'Fifine'], - ['indictor', true], - ['price', 8000], - ['color', 'Black'], + ["brand", "Fifine"], + ["indictor", true], + ["price", 8000], + ["color", "Black"], ]; console.log(Object.fromEntries(arr)); // { brand: 'Fifine', indictor: true, price: 8000, color: 'Black' } @@ -1083,20 +1104,20 @@ console.log(Object.fromEntries(arr)); // { brand: 'Fifine', indictor: true, pric ```js const microphone = { - brand: 'Fifine', - indictor: true, - price: 8000, - color: 'Black', - startRecording() { - console.log('recording started'); - }, - stopRecording() { - console.log('recording stopped'); - }, + brand: "Fifine", + indictor: true, + price: 8000, + color: "Black", + startRecording() { + console.log("recording started"); + }, + stopRecording() { + console.log("recording stopped"); + }, }; function startRecording() { - console.log('recording started'); + console.log("recording started"); } startRecording(); @@ -1112,11 +1133,11 @@ microphone.startRecording(); ```js function uuidv4() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { - const r = (Math.random() * 16) | 0; - const v = c == 'x' ? r : (r & 0x3) | 0x8; - return v.toString(16); - }); + return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { + const r = (Math.random() * 16) | 0; + const v = c == "x" ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); } ``` @@ -1128,21 +1149,21 @@ function uuidv4() { ```js const students = [ - { - id: uuidv4(), - name: 'Md Al-Amin', - email: 'alamin@test.com', - }, - { - id: uuidv4(), - name: 'Akib Ahmed', - email: 'akib@test.com', - }, - { - id: uuidv4(), - name: 'Elias Emon', - email: 'elias@test.com', - }, + { + id: uuidv4(), + name: "Md Al-Amin", + email: "alamin@test.com", + }, + { + id: uuidv4(), + name: "Akib Ahmed", + email: "akib@test.com", + }, + { + id: uuidv4(), + name: "Elias Emon", + email: "elias@test.com", + }, ]; ``` @@ -1150,21 +1171,21 @@ const students = [ ```js const students = [ - { - id: '67de71e5-0eac-474f-ab51-850ba9b31ed5', - name: 'Md Al-Amin', - email: 'alamin@test.com', - }, - { - id: 'ebdf6b78-c32b-4b1d-8574-e8c655b05c1e', - name: 'Akib Ahmed', - email: 'akib@test.com', - }, - { - id: 'ee729e84-a84e-4adf-b32c-4647a7114d5b', - name: 'Elias Emon', - email: 'elias@test.com', - }, + { + id: "67de71e5-0eac-474f-ab51-850ba9b31ed5", + name: "Md Al-Amin", + email: "alamin@test.com", + }, + { + id: "ebdf6b78-c32b-4b1d-8574-e8c655b05c1e", + name: "Akib Ahmed", + email: "akib@test.com", + }, + { + id: "ee729e84-a84e-4adf-b32c-4647a7114d5b", + name: "Elias Emon", + email: "elias@test.com", + }, ]; ``` @@ -1184,9 +1205,9 @@ const students = [ ```js students.push({ - id: '0a2c956c-a9f4-48b9-83fa-551b432dfb2b', - name: 'Fahim Faisal', - email: 'fahim@test.com', + id: "0a2c956c-a9f4-48b9-83fa-551b432dfb2b", + name: "Fahim Faisal", + email: "fahim@test.com", }); ``` @@ -1197,18 +1218,18 @@ students.push({ আমরা দুইভাবে আপডেট করতে পারি। একটা হচ্ছে যাকে আপডেট করতে হবে find মেথডের মাধ্যমে সেই অবজেক্টকে বের করে তাকে আপডেট করা। আরেকটা হলো ঐ অবজেক্টের ইনডেক্সকে findIndex মেথডের মাধ্যমে বের করে সেটা ধরে আপডেট করা। অবজেক্ট ধরে যদি আপডেট করতে চাই সেক্ষেত্রে একটা সমস্যা আছে। সেটা একটু আমরা দেখি। ```js -const idToUpdate = 'ee729e84-a84e-4adf-b32c-4647a7114d5b'; +const idToUpdate = "ee729e84-a84e-4adf-b32c-4647a7114d5b"; const updatedData = { - name: 'Habiba Akhtar', - email: 'habiba@test.com', + name: "Habiba Akhtar", + email: "habiba@test.com", }; let updatedObj = students.find((item) => item.id === idToUpdate); updatedObj = { - id: idToUpdate, - ...updatedData, + id: idToUpdate, + ...updatedData, }; -console.log('Updated', students); +console.log("Updated", students); /* Updated [ { @@ -1238,18 +1259,18 @@ Updated [ কিছুই আপডেট হলো না। কারণ আমরা অবজেক্ট অ্যাসাইন করছি। আর যেহেতু অ্যাসাইন করছি সেহেতু এর রেফারেন্সও আলাদা হয়ে গেছে। আলাদা রেফারেন্সের কারণে আমার আপডেট কাজ করছে না। এবার আসি ইনডেক্স বের করে কিভাবে আপডেট করতে পারি সেটা নিয়ে। ```js -const idToUpdate = 'ee729e84-a84e-4adf-b32c-4647a7114d5b'; +const idToUpdate = "ee729e84-a84e-4adf-b32c-4647a7114d5b"; const updatedData = { - name: 'Habiba Akhtar', - email: 'habiba@test.com', + name: "Habiba Akhtar", + email: "habiba@test.com", }; const updatedIndex = students.findIndex((item) => item.id === idToUpdate); students[updatedIndex] = { - ...students[updatedIndex], - ...updatedData, + ...students[updatedIndex], + ...updatedData, }; -console.log('Updated', students); +console.log("Updated", students); ``` তিনটা ডট দেয়াকে জাভাস্ক্রিপ্টে বলে স্প্রেড অপারেটর। এর মানে হলো অরিজিনাল অবজেক্টে যা যা আছে সবই থাকবে। আর নতুন ডাটা অনুযায়ী সেটা আপডেট হবে। যখন কোনো কিছু রিঅ্যাসাইনের কাজ আসবে তখন আমরা find ব্যবহার না করে findIndex ব্যবহার করবো। এই আপডেট করা মোটামুটি রকমের কমপ্লেক্স। তাই এর কমপ্লেক্সিটি আমরা O(n) হিসেবে ধরতে পারি। @@ -1275,15 +1296,15 @@ console.log(filteredStudents); ```js for (let i = 0; i < students.length; i++) { - console.log(students[i].name); + console.log(students[i].name); } for (let i in students) { - console.log(students[i].name); + console.log(students[i].name); } for (let student of students) { - console.log(student.name); + console.log(student.name); } ``` @@ -1295,21 +1316,21 @@ for (let student of students) { ```js const students = { - '67de71e5-0eac-474f-ab51-850ba9b31ed5': { - id: '67de71e5-0eac-474f-ab51-850ba9b31ed5', - name: 'Md Al-Amin', - email: 'alamin@test.com', - }, - 'ebdf6b78-c32b-4b1d-8574-e8c655b05c1e': { - id: 'ebdf6b78-c32b-4b1d-8574-e8c655b05c1e', - name: 'Akib Ahmed', - email: 'akib@test.com', - }, - 'ee729e84-a84e-4adf-b32c-4647a7114d5b': { - id: 'ee729e84-a84e-4adf-b32c-4647a7114d5b', - name: 'Elias Emon', - email: 'elias@test.com', - }, + "67de71e5-0eac-474f-ab51-850ba9b31ed5": { + id: "67de71e5-0eac-474f-ab51-850ba9b31ed5", + name: "Md Al-Amin", + email: "alamin@test.com", + }, + "ebdf6b78-c32b-4b1d-8574-e8c655b05c1e": { + id: "ebdf6b78-c32b-4b1d-8574-e8c655b05c1e", + name: "Akib Ahmed", + email: "akib@test.com", + }, + "ee729e84-a84e-4adf-b32c-4647a7114d5b": { + id: "ee729e84-a84e-4adf-b32c-4647a7114d5b", + name: "Elias Emon", + email: "elias@test.com", + }, }; ``` @@ -1321,9 +1342,9 @@ const students = { ```js const std = { - id: uuidv4(), - name: 'Feroz Khan', - email: 'feroz@test.com', + id: uuidv4(), + name: "Feroz Khan", + email: "feroz@test.com", }; students[std.id] = std; @@ -1336,14 +1357,14 @@ students[std.id] = std; যেহেতু এটা অ্যারে না সেহেতু এখানে find বা findIndex কিছুই কাজ করবে না। তাহলে কিভাবে আপডেট করবো। খুব সহজ। চলুন দেখা যাক। ```js -const idToBeUpdated = 'ee729e84-a84e-4adf-b32c-4647a7114d5b'; +const idToBeUpdated = "ee729e84-a84e-4adf-b32c-4647a7114d5b"; const updatedData = { - name: 'HM Azizul', - email: 'azizul@test.com', + name: "HM Azizul", + email: "azizul@test.com", }; students[idToBeUpdated] = { - ...students[idToBeUpdated], - ...updatedData, + ...students[idToBeUpdated], + ...updatedData, }; ``` @@ -1364,7 +1385,7 @@ delete students[idToBeUpdated]; যদি আমাদের কোনো অবজেক্টের কী জানা থাকে তাহলে ১ সেকেন্ডের মধ্যে আমরা সেই অবজেক্টকে পেয়ে যাবো। কিভাবে> দেখুন তাহলে- ```js -console.log(students['67de71e5-0eac-474f-ab51-850ba9b31ed5']); +console.log(students["67de71e5-0eac-474f-ab51-850ba9b31ed5"]); ``` জাস্ট এটুকুই। আর এটার কমপ্লেক্সিটিও O(1)। @@ -1375,7 +1396,7 @@ console.log(students['67de71e5-0eac-474f-ab51-850ba9b31ed5']); ```js for (let key in students) { - console.log(students[key].name); + console.log(students[key].name); } ``` @@ -1383,8 +1404,8 @@ for (let key in students) { ```js Object.keys(students).forEach((key) => { - const student = students[key]; - console.log(student.name); + const student = students[key]; + console.log(student.name); }); ``` @@ -1392,7 +1413,7 @@ Object.keys(students).forEach((key) => { ```js Object.values(students).forEach((student) => { - console.log(student.name); + console.log(student.name); }); ``` @@ -1406,54 +1427,54 @@ Object.values(students).forEach((student) => { const arr = []; const arrToObj = {}; for (let i = 0; i < 5000000; i++) { - const o = { - id: i, - value: i, - }; - arr.push(o); - arrToObj[i] = o; + const o = { + id: i, + value: i, + }; + arr.push(o); + arrToObj[i] = o; } -console.time('array'); +console.time("array"); let id = 4999999; const obj = arr.find((item) => item.id === id); obj.value = 555; -console.timeEnd('array'); // 104.901ms +console.timeEnd("array"); // 104.901ms -console.time('obj'); +console.time("obj"); arrToObj[id].value = 999; -console.timeEnd('obj'); // 0.019ms +console.timeEnd("obj"); // 0.019ms ``` অ্যারের অপারেশনে সময় লেগেছে ১০৪.৯০১ মিলিসেকেন্ড আর অবজেক্টের অপারেশনে লেগেছে ০.০১৯ মিলিসেকেন্ড। ```js -console.time('array'); +console.time("array"); arr.unshift({ - id: 5000000, - value: 5000000, + id: 5000000, + value: 5000000, }); -console.timeEnd('array'); // 15.084ms +console.timeEnd("array"); // 15.084ms -console.time('obj'); +console.time("obj"); arrToObj[5000000] = { - id: 5000000, - value: 5000000, + id: 5000000, + value: 5000000, }; -console.timeEnd('obj'); // 0.018ms +console.timeEnd("obj"); // 0.018ms ``` অ্যারের জন্য লেগেছে ১৫.০৮৪ মিলিসেকেন্ড আর অবজেক্টের ক্ষেত্রে লেগেছে ০.০১৮ মিলিসেকেন্ড। ```js -console.time('array'); +console.time("array"); const index = arr.findIndex((item) => item.id === 4000000); arr.splice(index, 1); -console.timeEnd('array'); // 93.135ms +console.timeEnd("array"); // 93.135ms -console.time('obj'); +console.time("obj"); delete arrToObj[4000000]; -console.timeEnd('obj'); // 0.015ms +console.timeEnd("obj"); // 0.015ms ``` অ্যারের ক্ষেত্রে লেগেছে ৯৩.১৩৫ মিলিসেকেন্ড আর অবজেক্টের ক্ষেত্রে লেগেছে ০.০১৫ মিলিসেকেন্ড।