คุณสมบัติหนึ่งของฟังก์ชัน Array.prototype.sort() คือมันเป็นอัลกอริธึมการจัดเรียงแบบแทนที่ ซึ่งหมายความว่าจะไม่สร้างสำเนาใหม่ของอาร์เรย์ที่จะจัดเรียง แต่จะจัดเรียงอาร์เรย์โดยไม่ต้องใช้พื้นที่เพิ่มเติม ทำให้มีประสิทธิภาพมากขึ้นและ นักแสดงแต่บางครั้งลักษณะนี้นำไปสู่สถานการณ์ที่น่าอึดอัดใจ
มาทำความเข้าใจกับตัวอย่างกัน สมมติว่า เรามีเนมอาร์เรย์ที่มีตัวอักษรสตริงบางตัว เราต้องการที่จะรักษาลำดับของอาร์เรย์นี้ไว้เหมือนเดิมและต้องการอาร์เรย์อื่นที่มีองค์ประกอบที่เหมือนกันเป็นอาร์เรย์ชื่อแต่จัดเรียงตามตัวอักษร
เราสามารถทำสิ่งนี้ได้ -
const names = ['Rakesh', 'Mukesh', 'Ram', 'Anshul', 'Dheeraj']; let sortedNames = names; sortedNames = sortedNames.sort(); console.log(names); console.log(sortedNames);
แต่อย่างที่เราทราบใน JavaScript อาร์เรย์ก็เป็นอ็อบเจ็กต์เช่นกัน และอ็อบเจ็กต์จะถูกคัดลอกโดยการอ้างอิงและไม่ใช่ตามค่า ดังนั้นการจัดเรียงอาร์เรย์หนึ่งจะส่งผลให้เกิดการจัดเรียงของทั้งสองอาร์เรย์ ซึ่งเราไม่ต้องการอย่างเห็นได้ชัด
วิธีแก้ไข
1. ใช้ slice() ในขณะที่เริ่มต้นอาร์เรย์ใหม่
ตัวอย่าง
const names = ['Rakesh', 'Mukesh', 'Ram', 'Anshul', 'Dheeraj']; let sortedNames = names.slice(); sortedNames = sortedNames.sort(); console.log(names); console.log(sortedNames);
จริง ๆ แล้วเมธอด slice() จะคืนค่าสำเนาตื้น คัดลอกไปยังอาร์เรย์ใหม่ของอาร์เรย์ที่ใช้ หากไม่มีอาร์กิวเมนต์ ให้คัดลอกตั้งแต่ต้นจนจบ
แม้ว่าวิธีนี้จะไม่ได้มีประสิทธิภาพมากนัก เพราะมันรวมถึงการเริ่มต้นอาร์เรย์ใหม่และมีผลเฉพาะกับอาร์เรย์ของตัวอักษรสตริง / หมายเลข แต่วิธีที่สองนั้นมีประสิทธิภาพมากกว่าเล็กน้อยและทำงานได้ดีกับอาร์เรย์ของวัตถุเช่นกัน
2. ใช้ JSON.stringify() / JSON.parse()
ตัวอย่าง
const names = ['Rakesh', 'Mukesh', 'Ram', 'Anshul', 'Dheeraj']; let sortedNames = JSON.parse(JSON.stringify(names)); sortedNames = sortedNames.sort(); console.log(names); console.log(sortedNames);
การแปลงอาร์เรย์เป็นสตริง JSON และกลับเป็นอาร์เรย์ในลักษณะบังคับให้คอมไพเลอร์ tonot คัดลอกโดยการอ้างอิง
ผลลัพธ์สำหรับทั้งสองวิธีจะเหมือนกันในคอนโซล -
ผลลัพธ์
[ 'Rakesh', 'Mukesh', 'Ram', 'Anshul', 'Dheeraj' ] [ 'Anshul', 'Dheeraj', 'Mukesh', 'Rakesh', 'Ram' ]