javascript - วิธีจัดเรียงคุณสมบัติของอ็อบเจ็กต์เป็นพารามิเตอร์ในฟังก์ชัน?
สมมติว่าเรามีฟังก์ชันที่มีพารามิเตอร์:
function do(classId: number, schoolId: number, pupilId: number, teacherId: number, roomId: number) {
}
ฉันต้องเรียกใช้ฟังก์ชันนี้โดยส่งออบเจ็กต์ที่มีคุณสมบัติซึ่งควรเติมลงในพารามิเตอร์ของฟังก์ชันที่สอดคล้องกัน เช่น:
กรณีที่หนึ่ง:
let obj1 = {classId: 1, roomId: 3};
do(obj1); // passed only classId, roomId
กรณีที่สอง:
let obj2 = {schoolId: 5, pupilId: 4};
do(obj2); // passed only schoolId, pupilId
คำตอบ #1
ถ้าฉันเข้าใจคุณถูกต้อง คุณต้องการแบบนี้:
const Do: (
arg: {
classId?: number;
schoolId?: number;
pupilId?: number;
teacherId?: number;
roomId?: number;
}
) => any = ({ classId, schoolId, pupilId, teacherId, roomId }) => {};
ฉันได้แทนที่รายการของพารามิเตอร์ด้วยพารามิเตอร์เดียว ซึ่งเป็นรูปแบบการทำลายวัตถุ
โปรดทราบว่าคุณไม่สามารถใช้ do เป็นชื่อผู้ระบุได้ ดังนั้นฉันจึงเปลี่ยนเป็น Do.
ฟังก์ชัน JS แบบคลาสสิกก็ไม่ค่อยเป็นมิตรกับชนิดข้อมูลและ TypeScript ดังนั้นฉันจึงเขียนใหม่โดยใช้ฟังก์ชันลูกศร
สนามเด็กเล่น
คำตอบ #2
วิธีที่ดีกว่า
ก่อนอื่น การปรับโค้ดฟังก์ชันให้รับพารามิเตอร์เป็นอ็อบเจ็กต์เดียวเหมือนในคำตอบของ Nurbol (ซึ่งผมให้คะแนนขึ้น) ตามความคิดเห็นของผมเป็นวิธีแก้ไขที่ดีกว่า รายการอาร์กิวเมนต์ยาวๆ ของตัวเลขมักจะใช้งานยากและมีแนวโน้มที่จะเกิดข้อผิดพลาด
คำตอบตามตัวอักษร
อย่างไรก็ตาม หากคุณต้องการแปลงคีย์ของออบเจ็กต์เป็นรายการอาร์กิวเมนต์สำหรับฟังก์ชันที่มีอยู่จริงๆ (ตัวอย่างเช่น สมมติว่า do() อยู่นอกการควบคุมของคุณและไม่สามารถปรับโครงสร้างใหม่ได้) ตามที่คำถามของคุณระบุ คุณยังมีตัวเลือกบางอย่าง
วิธีการที่ง่ายและตรงไปตรงมาคือการใช้ Object.values() ซึ่งจะทำการแปลงค่าของอ็อบเจ็กต์ให้เป็นอาร์เรย์ที่สามารถกระจายเป็นอาร์กิวเมนต์ของฟังก์ชันได้:
do(...Object.values(obj));
อย่างไรก็ตาม ลำดับของค่าจะไม่ได้รับประกัน (สิ่งเดียวกันนี้ใช้กับการวนซ้ำคีย์ของออบเจกต์ทั้งหมด เช่น for..in หรือ forEach()) ดังนั้นนี่ไม่ใช่ความคิดที่ดีหากลำดับของอาร์กิวเมนต์ฟังก์ชันของคุณมีความสำคัญ ซึ่งมันชัดเจนว่าในกรณีของคุณมีความสำคัญ
เพื่อรับประกันลำดับพารามิเตอร์ที่ถูกต้อง คุณจะต้อง กำหนดลำดับของคีย์อย่างชัดเจน ด้วยวิธีใดวิธีหนึ่ง นี่คือตัวอย่างของฟังก์ชันทั่วไปที่รับออบเจ็กต์และอาร์เรย์ของคีย์ตามลำดับ จากนั้นใช้ array.reduce() เพื่อสร้างอาร์เรย์รายการอาร์กิวเมนต์ตามลำดับ:
function orderedArgs(obj: object, orderedKeys: string[]): any[] {
return orderedKeys.reduce((args, key) => {
args[orderedKeys.indexOf(key)] = obj[key as keyof object];
return args;
}, new Array(orderedKeys.length));
}
const argsOrder = ["classId", "schoolId", "pupilId", "teacherId", "roomId"];
const obj1 = { classId: 1, roomId: 3 };
doFn(...orderedArgs(obj1, argsOrder)); // passes: 1, undefined, undefined, undefined, 3
const obj2 = { schoolId: 5, pupilId: 4 };
doFn(...orderedArgs(obj2, argsOrder)); // passes: undefined, 5, 4, undefined, undefined
คุณสามารถทำให้สิ่งนี้เป็นนามธรรมมากขึ้นด้วยฟังก์ชันช่วยเหลือ:
const callDo = (obj: object) => doFn(...orderedArgs(obj, ["classId", "schoolId", "pupilId", "teacherId", "roomId"]));
callDo({ classId: 1, roomId: 3 }); // passes: 1, undefined, undefined, undefined, 3
callDo({ schoolId: 5, pupilId: 4 }); // passes: undefined, 5, 4, undefined, undefined
