۱۰ ترفند جاوا اسکریپتی برای افزایش سرعت کدنویسی

Top 20 JavaScript Tips and Tricks to Increase Your Speed and Efficiency

۱۰ ترفند جاوا اسکریپتی برای افزایش سرعت کدنویسی

ما در زندگی روزمره خود به عنوان توسعه دهنده کدهای زیادی می نویسیم. به طور مثال تابع تعریف می کنیم، آرایه مرتب می کنیم، جست و جو می کنیم، مقادیر یکتا را پیدا می کنیم و الی آخر. از آنجایی این کارها را زیاد انجام می دهیم بهتر است چند ترفند را یاد بگیریم تا بتوانیم:

  • تعداد خطوط کدهای نوشته شده را کم کنیم.
  • در مسابقات کدنویسی پیشرفت کنیم.
  • سرعت پیشرفت پروژه هایمان را بیشتر کنیم.

اکثر ترفندهای توضیح داده شده در این مقاله بر اساس قابلیت های ECMAScript6 هستند.

۱. مقدار هی اولیه به آرایه ها

زمانی که نیاز دارید یک آرایه تعریف کرده و مقدار اولیه آن را روی پنج رشته خالی یا پنج صفر یا پنج null بگذارید باید به صورت دستی عمل کنید:

const myArray = ["", "", "", "", ""]

اما روش سریع تری نیز برای انجام این کار وجود دارد:

const myArray = Array(5).fill('');

این کار یک آرایه پنج عضوی ایجاد می کند که همه آن ها مقدار رشته خالی را دارند.

شما می توانید این کار را برای آرایه های دو بعدی (آرایه های تو در تو) نیز انجام بدهید اما باید از تابع map استفاده کنید:

const matrix = Array(5).fill(0).map(()=>Array(5).fill(0));

خروجی چنین دستوری یک آرایه دو بعدی است، یعنی آرایه ای که پنج آرایه دیگر را به عنوان اعضای خود دارد و هر کدام از این آرایه ها پنج عضو صفر دارند:

// ساختار آرایه

[Array(5), Array(5), Array(5), Array(5), Array(5)]




// ساختار هر کدام از اعضای آرایه

0: (5) [0, 0, 0, 0, 0]

1: (5) [0, 0, 0, 0, 0]

2: (5) [0, 0, 0, 0, 0]

3: (5) [0, 0, 0, 0, 0]

4: (5) [0, 0, 0, 0, 0]

۲. جمع، کوچکترین و بزرگترین عضو

تابع reduce از توابع کمتر شناخته شده در جاوا اسکریپت برای افراد مبتدی است اما از قدرت بسیار زیادی برخوردار است. فرض کنید آرایه زیر را داشته باشید:

const array = [5, 4, 7, 8, 9, 2];

در صورتی که بخواهید مجموعه تمام اعضای آرایه را حساب کنید می توانید بدین شکل عمل کنید:

array.reduce((a, b) => a + b);

اگر بخواهید بزرگترین عضو یک آرایه را پیدا کنید می توانید از این روش استفاده کنید:

array.reduce((a, b) => (a > b ? a : b));

و در نهایت اگر بخواهید کوچکترین عضو را پیدا کنید باید دقیقا برعکس مقایسه بالا را بنویسید:

array.reduce((a, b) => (a < b ? a : b));

البته روش بسیار ساده دیگری نیز وجود دارد:

const array = [5, 4, 7, 8, 9, 2];




Math.min(...array);

Math.max(...array);

به همین سادگی می توانیم بیشترین مقدار و کمترین مقدار را پیدا کنیم. من پیشنهاد می کنم همیشه از روش ساده تر استفاده کنید اما به هر حال باید بدانید که روش بالا کُند تر از reduce است بنابراین اگر سرعت برایتان مهم می باشد بهتر است reduce را در نظر بگیرید.

۳. مرتب کردن آرایه های عددی، رشته ای و شیء

ما برای مرتب کردن بعضی از آرایه ها به توابع پیش فرض جاوا اسکریپتی به نام sort و reverse دسترسی داریم اما در برخی از آرایه های دیگر مانند آرایه های حاوی شیء چطور؟ در این بخش می خواهیم در اینباره صحبت کنیم.

برای مرتب کردن آرایه های عددی هیچ مشکلی نداریم:

const array = [40, 100, 1, 5, 25, 10];

array.sort((a, b) => a - b);

// خروجی

// (6) [1, 5, 10, 25, 40, 100]




array.sort((a, b) => b - a);

// خروجی

// (6) [100, 40, 25, 10, 5, 1]

این بخش نباید برای شما جدید باشد اما نکته خاصی دارد. توابع sort و reverse از الگوریتم های in-place استفاده می کنند، یعنی به جای آنکه مانند توابعی مثل ()map یک آرایه دیگر را برایتان برگردانند، همان آرایه پاس داده شده را ویرایش می کنند. این نکته بسیار مهم است چرا که اگر این توابع را روی آرایه پاس داده شده به تابع خود صدا بزنید، آرایه برای کل کدهایتان تغییر می کند و هر کدی که از آن آرایه استفاده کند تحت تاثیر خواهد بود.

سوال بعدی من این است که اگر اعضای آرایه به جای عدد، رشته باشند چطور؟ به مثال زیر توجه کنید:

const stringArr = ["Joe", "Kapil", "Steve", "Musk"];




stringArr.sort();

// خروجی

// (4)[("Joe", "Kapil", "Musk", "Steve")];




stringArr.reverse();

// خروجی

// (4)[("Steve", "Musk", "Kapil", "Joe")];

همانطور که می بینید تابع sort مقادیر موجود در آرایه را بر اساس حروف الفبای انگلیسی مرتب می کند در حالی که تابع reverse همین کار را به صورت برعکس انجام می دهد. سوال بعدی من اینجاست که اگر این رشته ها به زبان فارسی باشند آیا باز هم مرتب می شوند؟ پاسخ مثبت است:

const stringArr = ["امیر", "احمد", "حسین", "مهدی"];




stringArr.sort();

// خروجی

// (4)[ "مهدی", "حسین", "امیر", "احمد" ]




stringArr.reverse();

// خروجی

// (4)[ "احمد", "امیر", "حسین", "مهدی" ]

توجه داشته باشید که اگر کد بالا را در سیستم خود (مثلا در ترمینال یا VS Code) اجرا کنید ممکن است نتیجه را برعکس ببینید و تصور کنید که متد های sort و reverse در فارسی به صورت برعکس کار می کنند اما اینطور نیست. زبان فارسی از راست به چپ (RTL) است بنابراین فقط ظاهر نمایش آن ها ممکن است برایتان برعکس باشد اما در اصل همه چیز صحیح کار می کند.

آخرین حالت نیز آرایه هایی هستند که اعضایشان یک شیء است! به نظر شما متد sort و reverse چه تاثیری روی این دسته از آرایه ها دارند؟ به مثال زیر توجه کنید:

const objectArr = [

  { first_name: "Lazslo", last_name: "Jamf" },

  { first_name: "Pig", last_name: "Bodine" },

  { first_name: "Pirate", last_name: "Prentice" },

];

objectArr.sort((firstEl, secondEl) =>

  firstEl.last_name.localeCompare(secondEl.last_name)

);




// خروجی

// (3) [{…}, {…}, {…}]




// 0: {first_name: "Pig", last_name: "Bodine"}

// 1: {first_name: "Lazslo", last_name: "Jamf"}

// 2: {first_name: "Pirate", last_name: "Prentice"}

// length: 3

همانطور که مشخص است شما نمی توانید متد sort را به صورت عادی روی آرایه های شیء ای صدا بزنید. برای حل این مشکل باید یک متد را به sort پاس بدهید. این متد دو مقدار firstEl و secondEl را می گیرد که به ترتیب عضو اول و عضو دوم از آرایه هستند و سپس همینطور تا عضو آخر گردش می کنیم. در اینجا خودتان باید مشخص کنید که نحوه مرتب شدن اعضا چطور باشد. در جاوا اسکریپت متدی به نام localeCompare را داریم که مشخص می کند یک رشته بعد یا قبل از رشته دیگری آمده است. اگر رشته ما بعد از رشته مورد نظر آمده باشد یک عدد مثبت و اگر قبل از آن آمده باشد یک عدد منفی توسط تابع localeCompare برگردانده خواهد شد. اگر دو رشته یکسان باشند نیز عدد صفر برگردانده می شود. ما نیز این تابع را روی last_name پیاده کرده ایم و عدد برگردانده شده را return کرده ایم تا تابع sort بداند با هر کدام چه کاری انجام بدهد.

۴. فیلتر کردن مقادیر شبه غلط (falsy)

مقادیر falsy مقادیری هستند که ممکن است false نباشند اما در مقایسه ها معادل آن در نظر گرفته می شوند (مثلا 0 یا undefined یا null یا false یا رشته های خالی). در برخی از مواقع لازم است این مقادیر را از یک آرایه حذف کنید. چطور می توانیم این کار را انجام بدهیم؟

برای انجام این کار تنها کافی است که تایپ Boolean را فیلتر کنید:

const array = [3, 0, 6, 7, "", false];

array.filter(Boolean);




// خروجی

// (3)[(3, 6, 7)];

تابع filter در جاوا اسکریپت معمولا یک تابع را گرفته و بر اساس آن اعضای خاصی را از آرایه حذف می کند اما در اینجا فقط تایپ Boolean را به آن داده ایم بنابراین تمام این مقادیر از آرایه ما حذف شده است. دقت کنید که الگوریتم تابع filter به شکل in-place نیست بنابراین آرایه اصلی را ویرایش نمی کند بلکه نسخه تصحیح شده ای از آرایه را برمی گرداند.

۵. اپراتور منطقی به جای شرط if

در بخش های مختلفی از برنامه هایی که می نویسیم نیاز به شرط های if داریم اما در برخی اوقات این شرط ها آنچنان ساده هستند که استفاده از یک شرط if کامل زیاده نویسی می شود یا اینکه درون یک شرط if مجبور به نوشتن شرط های if دیگری می شویم.

برای جلوگیری از چنین حالت هایی می توانید از اپراتورهای منطقی جاوا اسکریپتی به جای شرط if استفاده کنید. به مثال زیر توجه کنید:

function doSomething(arg1 = 10) {

  return arg1;

}




let foo = 10;




foo === 10 && doSomething();

// معادل دستور زیر است:

// if (foo == 10) then doSomething();

// خروجی عدد ۱۰ است




foo === 5 || doSomething();

// معادل دستور زیر است:

// if (foo != 5) then doSomething();

// خروجی عدد ۱۰ است

همانطور که می بینید && برابر با حالتی است که foo===10 باشد و اگر اینطور بود تابع doSomething اجرا می شود اما || برابر با حالتی است که foo===5 نباشد و اگر اینطور بود تابع doSomething اجرا خواهد شد.

۶. حذف مقادیر تکراری

برنامه نویسانی که کمی قدیمی تر هستند برای حذف مقادیر تکراری از آرایه از روش زیر استفاده می کنند:

const array = [5, 5, 7, 8, 9, 2, 7, 5];

array.filter((item, idx, arr) => arr.indexOf(item) === idx);




// خروجی

// [ 5, 7, 8, 9, 2 ]

در این روش روی تک تک اعضای آرایه گردش می کنیم و هر زمان که ایندکس یک آیتم در آرایه با ایندکس گردش ما یکی نبود یعنی آن مقدار تکراری است بنابراین آن را حذف می کنیم. به طور مثال عدد 5 در آرایه بالا را در نظر بگیرید. این عدد دو بار تکرار شده است. تابع پاس داده شده به متد filter به صورت خودکار سه آرگومان را می گیرد: item که همان آیتم فعلی آرایه است، idx که ایندکس آن آیتم خاص است و arr که آرایه ما است. زمانی که از عوض اول (عدد ۵) شروع می کنیم با تابع indexOf به دنبال ایندکس آن در آرایه هستیم که صفر است. توجه داشته باشید که indexOf همیشه اولین نتیجه را برمی گرداند. یعنی در آرایه بالا که دو بار عدد ۵ را داریم، ایندکس اولین عدد ۵ را برمی گرداند که صفر است. از طرفی در اولین گردش هستیم بنابراین idx نیز صفر است. در گردش بعدی idx یک بوده اما indexOf برای عدد ۵ (عضو دوم) باز هم ایندکس صفر را برمی گرداند.

مشکل این روش این است که چنین روشی برای آرایه های بزرگ پاسخ خوبی نیست چرا که Big O برای آن از نوع Quadratic Time یا همان (O(N² است. اگر بخواهیم واقعا سرعت کار را بهتر کنیم باید از یک حلقه for استفاده کنیم تا بین اعضای آرایه گردش کنیم. طبیعتا استفاده از حلقه for نیز نیاز به نوشتن کدهای بیشتری دارد. آیا راه حل بهتری وجود ندارد؟

راه حل بهتر اینجاست که از Set ها استفاده نمایید که در نسخه ES6 جاوا اسکریپت معرفی شده اند. Set ها مجموعه ای از مقادیر یکتا و غیر تکراری هستند و نمی توانید در آن ها مقادیر تکراری وارد کنید.

const nonUnique = [...new Set(array)];




// خروجی

// [ 5, 7, 8, 9, 2 ]

این روش هم سریع است و هم با یک خط کد ساده انجام می شود. در نظر داشته باشید که Set ها در جاوا اسکریپت برخلاف پایتون ترتیب عناصر را حفظ می کنند بنابراین ترتیب عناصر شما بهم نخواهد ریخت.

۷. شیء شمارنده

در بسیاری از اوقات برای حل یک مشکل نیاز به ساخت یک یک شیء شمارنده داریم. اشیاء شمارنده اشیائی هستند که تعداد دفعات تکرار یک مقدار را می شمارند. به طور مثال رشته زیر را در نظر بگیرید:

let string = 'roxo.ir is a great platform for learning';

اگر بخواهیم تعداد دفعات تکرار شدن هر کدام از کاراکتر ها در این رشته را حساب کنیم به یک شیء شمارنده نیاز داریم. یک راه حل ساده برای انجام این کار بدین شکل است:

let string = "roxo.ir is a great platform for learning";




const table = {};

for (let char of string) {

  table[char] = table[char] + 1 || 1;

}

این کد روی تک تک کاراکتر های رشته string گردش می کند و خود کاراکتر را به عنوان ایندکس در شیء table قرار داده و دفعات تکرار آن را به صورت یک عدد و به عنوان مقدار برای آن ایندکس تعریف می کند. در این مثال از همان ترفند شماره ۵ (اپراتورهای منطقی) استفاده کرده ایم.

نتیجه اجرای کد بالا به شکل زیر است:

{

  r: 6,

  o: 4,

  x: 1,

  ".": 1,

  i: 3,

  " ": 6,

  s: 1,

  a: 4,

  g: 2,

  e: 2,

  t: 2,

  p: 1,

  l: 2,

  f: 2,

  m: 1,

  n: 2

}

همانطور که می بینید تک تک کاراکتر ها با تعداد تکرارشان در این شیء وجود دارد.

در صورتی که به جای اشیاء می خواهید از Map های جاوا اسکریپتی استفاده کنید، این کد برای شما مناسب است:

let string = "roxo.ir is a great platform for learning";




const countMap = new Map();




for (let i = 0; i < string.length; i++) {

  if (countMap.has(string[i])) {

    countMap.set(string[i], countMap.get(string[i]) + 1);

  } else {

    countMap.set(string[i], 1);

  }

}

Map ها نسبت به اشیاء سرعت بیشتری در حذف و اضافه کردن مقادیر دارند بنابراین ممکن است بیشتر به کمک شما بیاید. خروجی این کد به شکل زیر خواهد بود:

Map {

  "r" => 6,

  "o" => 4,

  "x" => 1,

  "." => 1,

  "i" => 3,

  " " => 6,

  "s" => 1,

  "a" => 4,

  "g" => 2,

  "e" => 2,

  "t" => 2,

  "p" => 1,

  "l" => 2,

  "f" => 2,

  "m" => 1,

  "n" => 2

}

۸. اپراتور ترنری برای جلوگیری از شرط های تو در تو

اپراتور ترنری (Ternary) می تواند شما را از نوشتن شرط های if تو در تو یا پشت سر هم حفظ کند. به مثال زیر توجه کنید:

function Fever(temp) {

  return temp > 97

    ? "Visit Doctor!"

    : temp < 97

    ? "Go Out and Play!!"

    : temp === 97

    ? "Take Some Rest!"

    : null;

}




// خروجی

// Fever(97): "Take Some Rest!"

// Fever(100): "Visit Doctor!"

همانطور که می بینید من به جای تعریف if های مختلف از اپراتور ترنری برای تعریف حالت های مختلف استفاده کرده ام.

۹. ادغام اشیاء

برای ادغام دو یا چند شیء روش های مختلفی در جاوا اسکریپت وجود دارد. روش های قدیمی تری مانند استفاده از حلقه ها وجود دارد اما بهترین روش، روش ES6 و استفاده از اپراتور spread است:

const user = {

  name: "Kapil Raghuwanshi",

  gender: "Male",

};

const college = {

  primary: "Mani Primary School",

  secondary: "Lass Secondary School",

};

const skills = {

  programming: "Extreme",

  swimming: "Average",

  sleeping: "Pro",

};




const summary = { ...user, ...college, ...skills };




// خروجی

// gender: "Male";

// name: "Kapil Raghuwanshi";

// primary: "Mani Primary School";

// programming: "Extreme";

// secondary: "Lass Secondary School";

// sleeping: "Pro";

// swimming: "Average";

در این روش اگر فیلدهایی با نام یکسان در اشیاء وجود داشته باشند، حتما در هم ادغام می شوند و یکی جایگزین دیگری می شوند بنابراین حتما این موضوع را در نظر داشته باشید.

۱۰. بهم ریختن اعضای آرایه

فرض کنید شما در حال طراحی یک بازی هستید و در این بازی باید ترتیب مقادیری را بهم بریزید (مثلا کارت های بازی را بین کاربران پخش کنید). در چنین حالتی نیاز به کدی داریم که ترتیب اعضای آرایه را جا به جا کند. برای این کار می توانیم از تابع Math.random استفاده کنیم:

const list = [1, 2, 3, 4, 5, 6, 7, 8, 9];

list.sort(() => {

  return Math.random() - 0.5;

});




// خروجی پس از یک بار صدا زدن

// (9) [2, 5, 1, 6, 9, 8, 4, 3, 7]




// خروجی پس از دو بار صدا زدن

// (9) [4, 1, 7, 5, 3, 8, 2, 9, 6]

همانطور که می بینید پس از هر بار صدا زدن این تابع، ترتیب اعضا جا به جا می شود.


منبع: وب سایت dev.to

نویسنده شوید

دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.