函式參數 (Function Arguments)

★★★★Draft

FromClean CodeCode Complete

📚 From the Books

函式參數 (Function Arguments)Functions

參數是函式與讀者之間的溝通成本。每多一個參數,讀者要理解的細節就多一份、測試要覆蓋的組合就多一輪。理想的參數數量是零,其次是一,其次是二;到了三個就該停下來問:這些參數是不是在告訴我,這裡藏著一個還沒被命名的概念?

🧠 Why It's a Problem

TIP

當函式看來需要三個以上參數,通常代表其中一些應該被包成一個物件makeCircle(x, y, radius)makeCircle(center, radius):把 x, y 包成 Point 不只是少一個參數,而是替一個本來就存在的概念命名。

⚖️ Case Study

前 — 參數爆炸 + 旗標參數
// 五個參數、順序難記,還有一個 boolean 旗標在內部分岔
function createUser(name, email, isAdmin, sendWelcome, timezone) {
  const user = { name, email, role: isAdmin ? "admin" : "member", timezone };
  if (sendWelcome) mailer.sendWelcome(user);
  return user;
}

// 呼叫端:true / false 是什麼意思?順序對嗎?
createUser("Bob", "bob@x.com", false, true, "Asia/Taipei");

isAdmin 讓函式做兩種角色、sendWelcome 讓它可能寄信也可能不寄——旗標把兩三個函式硬塞成一個。

後 — 參數物件 + 拆掉旗標
// 相關參數包成一個有名字的概念;旗標拆成兩個意圖清楚的函式
function createUser({ name, email, role = "member", timezone }) {
  return { name, email, role, timezone };
}

function createAdmin(profile) {
  return createUser({ ...profile, role: "admin" });
}

// 呼叫端自我說明,順序不再是負擔
const user = createUser({ name: "Bob", email: "bob@x.com", timezone: "Asia/Taipei" });
mailer.sendWelcome(user); // 「要不要寄信」由呼叫端明確決定,不藏在旗標裡

參數物件讓呼叫端自我說明、順序無關;把 isAdminsendWelcome 的分岔移出函式,每條路徑都只做一件事。

WARNING

Code Complete 補充:輸入、修改、輸出參數若混用,至少讓排列順序有慣例(輸入在前、輸出在後)並保持全專案一致;但更好的做法仍是盡量避免修改/輸出參數,改用回傳值。

🔑 Takeaways

✍️ My Notes

No notes yet — jot your takeaways or Q&A here.

📖 Further Reading