مرتب‌سازی داده‌ها، به‌ویژه زمانی که به صورت ساختاریافته ارائه شوند، نقش مهمی در افزایش خوانایی، درک بهتر و دسترسی سریع‌تر به اطلاعات ایفا می‌کند. متد sort در جاوااسکریپت یکی از ابزارهای کلیدی برای انجام این کار است. به‌عنوان یک توسعه‌دهنده، ممکن است نیاز داشته باشیم محصولات را بر اساس قیمت مرتب کنیم یا اسامی را به ترتیب حروف الفبا بچینیم تا بتوانیم سریع‌تر به داده‌های مرتبط دسترسی پیدا کنیم.

در جاوااسکریپت دو روش اصلی برای مرتب‌سازی آرایه‌ها وجود دارد: متد Array.prototype.sort و متد Array.prototype.toSorted. هر دو روش دارای رفتار پیش‌فرض در مرتب‌سازی هستند و در عین حال، امکان سفارشی‌سازی را نیز فراهم می‌کنند. به‌طور پیش‌فرض، هر دو این متدها ابتدا المنت‌ها را به رشته تبدیل می‌کنند و سپس آن‌ها را بر اساس مقادیر یونیت‌های کد UTF-16 به‌صورت صعودی مرتب می‌کنند.

در ادامه، خواهیم آموخت که چگونه می‌توانیم این دو روش را همراه با متد localeCompare و آبجکت Intl.Collator برای مرتب‌سازی‌های حساس به زبان، در آرایه‌هایی از نوع رشته، به کار بگیریم.

نحوه استفاده از متد ()sort در جاوااسکریپت

متد ()sort متد اصلی برای مرتب‌سازی آرایه‌ها در جاوااسکریپت است. این متد یک تابع اختیاری را به‌عنوان آرگومان می‌پذیرد. متد sort() المنت‌های آرایه را بر اساس این تابع مرتب کرده و سپس رفرنسی به همان آرایه اصلی بازمی‌گرداند. نکته کلیدی در اینجا این است که sort()، برخلاف برخی متدهای دیگر، آرایه اصلی را تغییر می‌دهد و آرایه جدیدی ایجاد نمی‌کند.

js
array.sort(compareFunction)

رفتار پیش‌فرض متد sort در غیاب تابع callback

تابع compareFunction رفتار مرتب‌سازی را تعیین می‌کند. اگر هیچ تابعی به آن ارسال نکنیم، متد sort() ابتدا المنت‌ها را به رشته تبدیل کرده و سپس آن‌ها را بر اساس مقادیر عددی واحدهای کد UTF-16 به‌صورت صعودی مرتب می‌کند. بیایید مثالی را بررسی کنیم:

js
const array = [20, 123, "🥚", "🐔"];
console.log(array.sort());

اگر به‌تازگی یادگیری جاوااسکریپت را آغاز کرده‌ایم، نتیجه اجرای کد بالا ممکن است برایمان عجیب باشد. نتیجه این مرتب‌سازی به شکل زیر می‌باشد:

js
const sortedArray = [ 123, 20, '🐔', '🥚' ];

همان‌طور که می‌بینیم، عدد 123 قبل از عدد 20 قرار گرفته، در حالی که 123 از 20 بزرگ‌تر است. این اتفاق به این دلیل رخ داده که متد sort() بدون استفاده از تابع callback فراخوانی شده است. در چنین حالتی، متد sort ابتدا المنت‌ها را به رشته تبدیل می‌کند و سپس آن‌ها را بر اساس ترتیب صعودی کدهای UTF-16 کاراکترهای آن رشته‌ها مرتب می‌کند.

تبدیل عددها به رشته و مرتب‌سازی آن‌ها بر اساس مقادیر یونیکد

المنت اول آرایه مرتب نشده عدد 20 است. هنگام تبدیل آن به رشته، به "20" تبدیل می‌شود. اولین کاراکتر این رشته "2" و کاراکتر دوم آن "0" است. مقدار یونیکد برای کاراکتر "2" برابر با U+0032 (معادل ۵۰ در مبنای دسیمال) و برای "0" برابر با U+0030 (معادل ۴۸در مبنای دسیمال) است.

از آنجا که این مقادیر در محدوده BMP قرار گرفته‌اند، مرورگر آن‌ها را با استفاده از یک واحد کد 16-bit منفرد در قالب UTF-16 نمایش می‌دهد:

js
const array = [20, 123, "🥚", "🐔"];

const string = array[0].toString(); // 20
console.log(string.length); // 2

console.log(string.charCodeAt(0)); // 50
console.log(string.charCodeAt(1)); // 48

به‌طور مشابه، المنت دوم آرایه مرتب نشده ما عدد ۱۲۳ است. هنگامی که این عدد صحیح به رشته تبدیل می‌شود، اولین کاراکتر آن "1"، دومین کاراکتر "2"، و سومین کاراکتر "3" خواهد بود.

مقدار یونیکد مربوط به کاراکتر "1" برابر با U+0031 (معادل ۴۹ در مبنای دسیمال)، برای کاراکتر "2" برابر با U+0032 (معادل ۵۰ در مبنای دسیمال) و برای "3" برابر با U+0033 (معادل 51 در مبنای دسیمال) است.

تمام این مقادیر نیز مانند قبل در محدوده BMP قرار دارند. بنابراین، هر یک از آن‌ها در کدگذاری UTF-16 به‌صورت یک واحد کد 16-bit منفرد رمزگذاری می‌شوند:

js
const array = [20, 123, "🥚", "🐔"];

const string = array[1].toString();
console.log(string.length); // 3

console.log(string.charCodeAt(0)); // 49
console.log(string.charCodeAt(1)); // 50
console.log(string.charCodeAt(2)); // 51

همانند اعداد صحیح، تمام انواع primitive جاوااسکریپت که مقدار آن‌ها undefined نیست، هنگام فراخوانی متد ()sort بدون تابع callback، ابتدا به رشته تبدیل می‌شوند. در مقابل، مقادیر undefined و slotهای خالی همگی در انتهای آرایه مرتب می‌شوند.

تفاوت در رمزگذاری ایموجی‌ها و استفاده از surrogate pair

در مثال ما، دو المنت پایانی آرایه ایموجی هستند. از آنجا که ایموجی‌ها از ابتدا به‌صورت رشته وارد آرایه شده‌اند، نیازی به تبدیل آن‌ها به رشته وجود ندارد؛ برخلاف سایر انواع primitive.

مقدار یونیکد اختصاص داده شده به ایموجی "🥚" برابر با U+1F95A (معادل ۱۲۹۳۷۰ در مبنای دسیمال) و برای ایموجی "🐔" برابر با U+1F414 (معادل ۱۲۸۰۲۰ در مبنای دسیمال) است. هر دو این مقادیر در Supplementary Plane قرار دارند و خارج از محدوده BMP هستند.

در کدگذاری UTF-16، کدهای یونیکدی که در Supplementary Plane قرار دارند، نمی‌توانند با یک واحد کد 16-bit منفرد رمزگذاری شوند. در عوض، برای نمایش این کاراکترها از جفت جانشین (surrogate pairها) استفاده می‌شود. این مسئله توضیح می‌دهد که چرا طول رشته‌ی "🥚" و "🐔" برابر با ۲ است:

js
console.log("🥚".length === 2) // true
console.log("🐔".length === 2) // true

در یک surrogate pair، اولین واحد کد UTF-16 به‌عنوان surrogate بالا (leading یا high surrogate) و دومین واحد به‌عنوان surrogate پایین (trailing یا low surrogate) شناخته می‌شود.

کد یونیکد اختصاص یافته به ایموجی "🥚" برابر با U+1F95A (معادل ۱۲۹۳۷۰ در مبنای دسیمال) است. در کدگذاری UTF-16، این مقدار به surrogate pair متناظر خود رمزگذاری می‌شود که شامل مقادیر U+D83E (معادل ۵۵۳۵۸) و U+DD5A (معادل ۵۶۶۶۶) است:

js
const array = [20, 123, "🥚", "🐔"];

const eggEmoji = array[2];

console.log(eggEmoji.charCodeAt(0)); // 55358
console.log(eggEmoji.charCodeAt(1)); // 56666

به‌طور مشابه، کد یونیکد اختصاص یافته به ایموجی "🐔" برابر با U+1F414 (معادل ۱۲۸۰۲۰ در مبنای دسیمال) است. در کدگذاری UTF-16، این مقدار به surrogate pair متناظر خود یعنی U+D83D (معادل ۵۵۳۵۷) و U+DC14 (معادل ۵۶۳۴۰) رمزگذاری می‌شود:

js
const array = [20, 123, "🥚", "🐔"];

const chickenEmoji = array[3];

console.log(chickenEmoji.charCodeAt(0)); // 55357
console.log(chickenEmoji.charCodeAt(1)); // 56340

مقایسه دقیق مقادیر کدهای UTF-16 در مرتب‌سازی

جاوااسکریپت هنگام تبدیل مقادیر غیررشته‌ای به رشته، از مقادیر عددی یونیت‌های کد UTF-16 کاراکترهای آن‌ها برای مرتب‌سازی استفاده می‌کند.

در مثال ما:

در نهایت، جاوااسکریپت از همین مقادیر عددی مربوط به واحدهای کد UTF-16 برای مرتب‌سازی استفاده می‌کند. به بیان دیگر، مرتب‌سازی نه بر اساس کاراکتر واقعی، بلکه بر اساس مقادیر عددی واحدهای کد UTF-16 آن‌ها انجام می‌شود.

در مثال ما، کوچک‌ترین مقدار ۴۹ است (برای "1" از ۱۲۳)، سپس ۵۰ (برای "2" از ۲۰)، بعد ۵۵۳۵۷ (surrogate ایموجی "🐔")، و نهایتاً ۵۵۳۵۸ (surrogate ایموجی "🥚").

بنابراین، دلیل اینکه عدد ۱۲۳ پیش از ۲۰ در آرایه مرتب‌شده ظاهر می‌شود همین است، با اینکه از نظر عددی بزرگ‌تر است. سپس ایموجی "🐔" و "🥚" به ترتیب در موقعیت سوم و چهارم قرار می‌گیرند.

رفتار متد sort در مواجهه با مقادیر undefined و المنت‌های خالی

در صورتی که آرایه دارای المنت‌های خالی (sparse) یا مقادیر undefined باشد، این المنت‌ها به انتهای آرایه منتقل می‌شوند. همچنین، slotهای خالی همیشه پس از مقادیر undefined مرتب می‌شوند.

اکنون بیایید آرایه مثال خود را به یک آرایه sparse تبدیل کرده و یک مقدار undefined و یک slot خالی به آن اضافه کنیم. نتیجه مرتب‌سازی این آرایه به‌صورت زیر خواهد بود:

js
const array = [20, undefined, , 123, "🥚", "🐔"];
console.log(array.sort()); // [ 123, 20, '🐔', '🥚', undefined, <1 empty item> ]

slot خالی و مقدار undefined اکنون در زمان اجرای کد، به انتهای آرایه منتقل می‌شوند.

ما رفتار متد ()sort جاوااسکریپت را زمانی که بدون تابع callback فراخوانی می‌شود بررسی کردیم. با این حال، این تنها روش مرتب‌سازی نیست؛ ما می‌توانیم این رفتار را با استفاده از ارسال یک تابع callback شخصی‌سازی کنیم.

چگونه آرایه‌ها را به ترتیب صعودی و نزولی در جاوااسکریپت مرتب کنیم؟

برای مرور آنچه در بخش قبلی گفتیم:

متد ()sort در جاوااسکریپت یک تابع compare اختیاری به عنوان callback می‌پذیرد. اگر تابعی تعریف نکنیم، جاوااسکریپت ابتدا المنت‌های آرایه را به رشته تبدیل می‌کند و سپس آن‌ها را با تکیه بر مقادیر عددی یونیت‌های کد UTF-16، به‌ترتیب صعودی مرتب می‌کند.

با این حال، رفتار پیش‌فرض مرتب‌سازی در جاوااسکریپت به‌ندرت پاسخگوی نیاز واقعی ما است. اغلب مواقع، نیاز داریم المنت‌ها را به‌صورت سفارشی، چه به ترتیب صعودی یا نزولی مرتب کنیم.

برای اعمال رفتار مرتب‌سازی دلخواه، باید یک تابع compare به عنوان callback ارسال نماییم. این تابع دو مقدار را به عنوان آرگومان دریافت می‌کند و فقط روی مقادیر undefined نشده اجرا می‌شود. مقادیر undefined و slotهای خالی همیشه در انتهای آرایه قرار می‌گیرند.

تابع compare باید به شکل زیر عمل کند:

کد زیر ساختار کلی یک تابع مقایسه را نشان می‌دهد:

js
const compareFunction = (arg1, arg2) => {
  if ("arg1 is to be sorted before arg2") {
    return "a negative number";
  } else if ("arg1 is to be sorted after arg2") {
    return "a positive number";
  }
  return "zero to maintain the original order of arg1 and arg2";
}

برای مرتب‌سازی آرایه‌ای از اعداد به ترتیب صعودی، تابع compare باید چیزی شبیه به کد زیر باشد:

js
const array = [23, -45, 78];
array.sort((a, b) => {
  if(a < b) return -1;
  if(a > b) return 1;
  return 0;
})

لازم نیست حتماً مقادیر بازگشتی -1 یا 1 باشند؛ هر مقدار عددی منفی یا مثبت معتبر است. تابع مرتب‌سازی بالا را می‌توانیم به شکلی کوتاه‌تر بنویسیم:

js
const array = [23, -45, 78];
array.sort((a, b) => a - b);

برای مرتب‌سازی آرایه به ترتیب نزولی، کافی است عملگر مقایسه در شرط if را تغییر دهیم. تابع compare در این حالت باید به شکل زیر باشد:

js
const array = [23, -45, 78];
array.sort((a, b) => {
  if(a > b) return -1;
  if(a < b) return 1;
  return 0;
})

یا می‌توانیم آن را به این صورت بنویسیم:

js
const array = [23, -45, 78];
array.sort((a, b) => b - a);

چگونه یک آرایه از آبجکت‌ها را در جاوااسکریپت مرتب کنیم؟

متد sort() تنها برای آرایه‌هایی از نوع عددی نیست. می‌توانیم از آن برای مرتب‌سازی آرایه‌ای از مقادیر primitive، آبجکت‌ها یا ترکیبی از هر دو استفاده کنیم.

برای مثال، فرض کنید یک آرایه از آبجکت‌ها داریم که بر اساس ویژگی name به ترتیب حروف الفبا مرتب شده‌اند:

js
const students = [
  { name: "Aggy Doe", age: 19 },
  { name: "Jane Doe", age: 16 },
  { name: "Kent Doe", age: 14 },
  { name: "Mark Doe", age: 19 },
];

می‌توانیم از متد sort() برای مرتب‌سازی این آبجکت‌ها بر اساس مقدار ویژگی age به صورت صعودی استفاده کنیم:

js
students.sort((a, b) => a.age - b.age);

اکنون آرایه مرتب شده students ما آماده است. ممکن است متوجه شویم که دو دانش‌آموز هم سن هستند. اگر از نسخه  ECMAScript 10 (سال ۲۰۱۹) یا بالاتر استفاده می‌کنیم، جاوااسکریپت پایداری مرتب‌سازی را تضمین می‌کند. نسخه‌های قدیمی‌تر ECMAScript چنین تضمینی ندارند.

در مرتب‌سازی پایدار، در صورت برابری مقادیر، ترتیب اولیه حفظ می‌شود. این موضوع را در آرایه students مشاهده می‌کنیم که در آن ترتیب اولیه دانش‌آموزانی که سن یکسان دارند، حفظ شده است:

js
const students = [
  { name: "Kent Doe", age: 14 },
  { name: "Jane Doe", age: 16 },
  { name: "Aggy Doe", age: 19 },
  { name: "Mark Doe", age: 19 },
];

همان‌طور که پیش‌تر توضیح داده شد، متد sort() یک آرایه جدید ایجاد نمی‌کند، بلکه آرایه اصلی را تغییر می‌دهد. اگر نمی‌خواهیم آرایه اصلی تغییر کند، ابتدا باید یک نسخه کپی از آن تهیه کنیم یا از متد جدید toSorted استفاده نماییم.

در مثال زیر، از متد structuredClone برای ایجاد کپی از آرایه اصلی قبل از مرتب‌سازی استفاده می‌کنیم. همچنین می‌توانیم از روش‌هایی مانند استفاده از سینتکس Spread (...) نیز بهره بگیریم:

js
const clone = structuredClone(students);
clone.sort((a, b) => a.age - b.age);

ویژگی‌های تابع compare در متد ()sort جاوااسکریپت

تابع compare که در متدهای sort() و toSorted() استفاده می‌شود، باید دارای ویژگی‌های مشخصی باشد تا بتواند رفتار مرتب‌سازی سفارشی را به‌درستی اجرا کند.
در غیر این صورت، اگر این تابع با آن ویژگی‌ها هم‌خوانی نداشته باشد، تعریف آن دقیق نخواهد بود و ممکن است در موتورهای مختلف جاوااسکریپت رفتارهای متفاوت و غیرقابل پیش‌بینی از خود نشان دهد.

تابع Pure

تابعی که به متد sort() ارسال می‌کنیم باید یک تابع pure باشد. این یعنی اگر آن را با یک جفت آرگومان مشخص فراخوانی کنیم، همیشه باید خروجی یکسانی را تولید کند.

خروجی این تابع باید فقط بر اساس ورودی‌های آن تعیین شود و نباید به هیچ state یا متغیر خارجی متکی باشد. همچنین، تابع نباید هیچ side effect‌ای ایجاد کند؛ یعنی نباید state خارجی را تغییر دهد یا عملیات I/O انجام دهد.

ضرورت pure بودن تابع compare از این‌جا ناشی می‌شود که هیچ تضمینی وجود ندارد که این تابع چه زمانی و به چه شکلی فراخوانی خواهد شد.

ویژگی بازتابی

تابع compare ما باید دارای ویژگی بازتابی (Reflexive) باشد. یعنی اگر دو آرگومان ورودی برابر باشند، تابع مقدار 0 را برگرداند تا ترتیب اولیه آن دو المنت در آرایه مرتب‌شده حفظ شود. مثال زیر این مفهوم را نشان می‌دهد:

js
console.log(compareFunction(a, a) === 0); // true

ویژگی پادمتقارن

تابع compare باید پادمتقارن (Anti-symmetric) باشد. به این معنی که مقادیر بازگشتی compareFunction(a, b) و compareFunction(b, a) باید علامت مخالف داشته باشند یا هر دو صفر باشند. برای مثال، اگر compareFunction(a, b) مقدار منفی بازگرداند، compareFunction(b, a) باید مقدار مثبت برگرداند و بالعکس.

ویژگی انتقالی

در نهایت، تابع compare باید ویژگی انتقالی (Transitive) را داشته باشد. یعنی اگر compareFunction(a, b) و compareFunction(b, c) هر دو دارای علامت مثبت، منفی یا صفر باشند، مقدار compareFunction(a, c) نیز باید همان علامت را داشته باشد.

نحوه استفاده از متد toSorted در جاوااسکریپت

تا اینجا متد ()sort در جاوااسکریپت را به‌صورت کامل بررسی کردیم. یکی از محدودیت‌های مهم این متد آن است که آرایه اصلی را تغییر می‌دهد. بنابراین اگر بخواهیم آرایه اولیه را دست‌نخورده نگه داریم، مجبوریم ابتدا یک نسخه کپی از آن تهیه نماییم.

برای رفع این مشکل، می‌توانیم از متد داخلی و کاربردی toSorted() استفاده کنیم. برخلاف sort()، متد toSorted() آرایه اصلی را تغییر نمی‌دهد، بلکه یک آرایه جدید return می‌کند.

ساختار متد toSorted() بسیار شبیه به sort() است. اگر این متد را بدون ارسال تابع compare فراخوانی کنیم، ابتدا المنت‌ها را به رشته تبدیل می‌کند و سپس آن‌ها را بر اساس مقادیر یونیت‌های کد UTF-16 به‌صورت صعودی مرتب می‌نماید:

js
const array = [20, 123, "🥚", "🐔"];
const sortedArray = array.toSorted();

console.log(array === sortedArray); // false
console.log(sortedArray); // [ 123, 20, '🐔', '🥚' ]

برای اعمال مرتب‌سازی سفارشی در متد toSorted()، باید همانند sort()، یک تابع compare ارسال کنیم. این تابع دو آرگومان دریافت می‌کند و مقادیر زیر را return می‌نماید:

در مثال زیر، آرایه‌ای از اعداد را به ترتیب صعودی مرتب می‌کنیم:

js
const array = [20, 123, -67];
const sortedArray = array.toSorted((a, b) => a - b);

console.log(array === sortedArray); // false
console.log(sortedArray); // [ -67, 20, 123 ]

همانند متد sort()، در toSorted() نیز المنت‌های undefined و slotهای خالی به انتهای آرایه منتقل می‌شوند. تابع compare برای این المنت‌ها فراخوانی نخواهد شد.

باید به این نکته توجه داشته باشیم که متد toSorted() یک قابلیت نسبتاً جدید در جاوااسکریپت است. بنابراین ممکن است هنوز در تمامی مرورگرها یا محیط‌های اجرایی جاوااسکریپت به‌طور کامل پشتیبانی نشود.

چگونه آرایه‌های رشته‌ای را در جاوااسکریپت مرتب کنیم؟

جاوااسکریپت دارای توابع داخلی locale-aware است که می‌توانیم برای مرتب‌سازی آرایه‌های رشته‌ای از آن‌ها استفاده کنیم. این توابع شامل آبجکت Intl.Collator و متد String.prototype.localeCompare هستند.

وظیفه اصلی آبجکت Intl.Collator انجام مقایسه رشته‌ای حساس به زبان و موقعیت مکانی است. زبان‌های مختلف قوانین متفاوتی برای مقایسه رشته‌ها دارند. می‌توانیم از Intl.Collator برای مرتب‌سازی رشته‌ای حساس به محل استفاده کنیم، مانند مثال زیر:

js
const swedishCollator = new Intl.Collator("sv");
const germanCollator = new Intl.Collator("de");

const data = ["Z", "a", "z", "ä"];
console.log(data.toSorted(swedishCollator.compare)); // [ 'a', 'z', 'Z', 'ä' ]
console.log(data.toSorted(germanCollator.compare));  // [ 'a', 'ä', 'z', 'Z' ]

متد Intl.Collator.prototype.compare یک جفت رشته را به عنوان آرگومان دریافت می‌کند و مقدار زیر را return می‌کند:

به همین دلیل می‌توانیم این تابع را به عنوان تابع compare به متد Array.prototype.sort() یا Array.prototype.toSorted() ارسال کنیم.

همچنین می‌توانیم رفتار مرتب‌سازی را با ارسال آرگومان دوم اختیاری به Intl.Collator شخصی‌سازی کنیم. مطالعه مستندات رسمی آن می‌تواند برای دریافت اطلاعات بیشتر مفید باشد.

به‌صورت مشابه، می‌توانیم از متد String.prototype.localeCompare نیز برای مرتب‌سازی آرایه‌های رشته‌ای استفاده کنیم. این متد با return کردن یک عدد، مشخص می‌کند که رشته فعلی قبل، بعد یا معادل رشته‌ی ورودی قرار دارد:

js
const referenceString = "Jane Doe";
console.log(referenceString.localeCompare("Chris Doe"));

اگر خروجی منفی باشد، رشته فعلی پیش از رشته مقایسه‌ای قرار می‌گیرد. اگر مقدار بازگشتی مثبت باشد، رشته فعلی پس از رشته ورودی قرار می‌گیرد؛ اگر صفر باشد، هر دو رشته معادل‌اند.

بنابراین می‌توانیم از متد localeCompare همراه با متدهای sort یا toSorted برای مرتب‌سازی الفبایی آرایه‌ای از رشته‌ها استفاده کنیم:

js
const names = [
  "Jane Doe",
  "Kim Doe",
  "Chris Doe",
  "Mia Doe",
]

names.sort((a, b) => a.localeCompare(b))
console.log(names)

در مرورگرها یا محیط‌هایی که API مربوط به Intl.Collator را پیاده‌سازی کرده‌اند، متد localeCompare در واقع به‌صورت داخلی از Intl.Collator استفاده می‌کند.

مرتب‌سازی آبجکت‌های مشابه آرایه در جاوااسکریپت با استفاده از sort و toSorted

در بخش‌های قبلی، از متدهای sort و toSorted به عنوان متدهای نمونه آرایه استفاده کردیم. اما مانند بسیاری از متدهای آرایه، این دو تابع در واقع توابع generic هستند. یعنی استفاده از آن‌ها محدود به آرایه‌ها نیست.

می‌توانیم از آن‌ها برای مرتب‌سازی آبجکت‌های شبه‌آرایه‌ای نیز استفاده کنیم. تنها شرط لازم این است که آبجکت مورد نظر دارای ویژگی length و کلیدهای عددی صحیح باشد، مانند مثال زیر:

js
const object = {
  0: 90,
  1: 34,
  2: -45,
  3: 12,
  length: 4,
};

Array.prototype.sort.call(object, (a, b) => a - b);
console.log(object); // { '0': -45, '1': 12, '2': 34, '3': 90, length: 4 }

در مثال بالا، جاوااسکریپت آبجکت داده‌شده را به ترتیب صعودی مرتب می‌کند. برای مرتب‌سازی نزولی نیز می‌توانیم تابع compare را تغییر دهیم. متد sort() آبجکت اصلی را تغییر می‌دهد و رفرنسی به همان آبجکت return می‌کند.

اگر نمی‌خواهیم آبجکت اصلی تغییر کند، می‌توانیم از متد toSorted استفاده کنیم. بر خلاف sort، متد toSorted یک آرایه‌ی جدید برمی‌گرداند، نه یک آبجکت:

js
const object = {
  0: 90,
  1: 34,
  2: -45,
  3: 12,
  length: 4,
};

const sortedObject = Array.prototype.toSorted.call(object, (a, b) => a - b);

console.log(sortedObject); // [ -45, 12, 34, 90 ]
console.log(sortedObject === object); // false

جمع‌بندی

متدهای sort و toSorted ابزارهای داخلی در جاوااسکریپت برای مرتب‌سازی آرایه‌ها هستند.

در حالت پیش‌فرض، هر دو متد ابتدا مقادیر آرایه را به رشته تبدیل می‌کنند و سپس آن‌ها را بر اساس مقادیر یونیت‌های کد UTF-16 به‌صورت صعودی مرتب می‌نمایند. با این حال، می‌توانیم با استفاده از یک تابع compare، رفتار مرتب‌سازی را به‌صورت دلخواه شخصی‌سازی کنیم.

تفاوت اصلی این دو متد در نحوه‌ی اثرگذاری آن‌ها بر آرایه است:

متد sort در جاوااسکریپت یک ابزار قدرتمند برای مرتب‌سازی مقادیر آرایه‌هاست که با تعریف تابع compare، قابلیت سفارشی‌سازی بالایی دارد.

همچنین بررسی کردیم که با ارسال تابع callback به این متدها، می‌توانیم مرتب‌سازی پیشرفته‌تری انجام دهیم؛ از جمله مرتب‌سازی آرایه‌هایی از نوع‌های primitive یا آبجکت‌ها بر اساس معیار دلخواه.

هر دو متد، توابع generic محسوب می‌شوند و حتی روی آبجکت‌های شبه‌آرایه‌ای (که دارای ویژگی length و کلیدهای عددی هستند) نیز قابل استفاده‌اند.

انتخاب بین این دو متد بستگی دارد به اینکه قصد داریم آرایه اصلی را تغییر دهیم یا خیر: