RESTful API 的 PUT 和 PATCH 是很常見的面試題。
最短回答是:
PUT通常代表整份資源的替換,PATCH通常代表局部更新。
但面試時最好再補上 request body 語意、idempotent,以及前後端 contract。
PUT 是什麼?
PUT 通常用來更新或替換某個資源。
PUT /api/users/123
Content-Type: application/json
{
"name": "Ray",
"email": "ray@example.com",
"role": "admin"
}語意上是:
把
/api/users/123這個資源更新成我送過去的完整內容。
如果後端採嚴格 REST 語意,你漏掉的欄位可能會被視為空值、預設值,或直接被移除。
PATCH 是什麼?
PATCH 通常用來局部更新資源。
PATCH /api/users/123
Content-Type: application/json
{
"name": "Ray Huang"
}語意上是:
只更新我送出的欄位,其他欄位維持不變。
這很適合表單只編輯部分欄位的場景。
PUT vs PATCH 比較
| 比較 | PUT | PATCH |
|---|---|---|
| 語意 | 替換整份資源 | 局部更新 |
| request body | 通常送完整資料 | 只送要改的欄位 |
| 常見用途 | 更新整個 profile、替換設定 | 修改名稱、狀態、單一欄位 |
| 風險 | 漏欄位可能覆蓋資料 | 後端要定義 partial update 規則 |
面試回答可以這樣講:
PUT 通常代表用 request body 替換指定資源,所以比較適合送完整資源;PATCH 則是 partial update,只送要修改的欄位。前端串接時我會確認後端 API contract,尤其是 PUT 漏欄位時到底是保留原值、清空,還是驗證失敗。
idempotent 是什麼?
idempotent 的意思是:
同一個請求執行一次或多次,最終結果應該一樣。
PUT 通常被設計成 idempotent。
PUT /api/users/123
{
"name": "Ray"
}送一次或三次,最後 name 都是 Ray。
PATCH 是否 idempotent 要看語意。
PATCH /api/users/123
{
"name": "Ray"
}這通常也是 idempotent。
但這種就不是:
PATCH /api/cart/123
{
"incrementQuantityBy": 1
}送多次結果會不同。
前端實務上要注意什麼?
1. 不要自己猜 API 語意
有些後端雖然用 PUT,實作上其實是 partial update。
有些 API 用 PATCH,但要求特定欄位必填。
所以前端要看 API 文件或和後端確認。
2. 表單送出要注意 dirty fields
如果是 PATCH,可以只送改過的欄位:
const payload = getDirtyFields(formValues, initialValues);
await fetch(`/api/users/${id}`, {
method: "PATCH",
body: JSON.stringify(payload),
});如果是 PUT,通常要送完整表單資料:
await fetch(`/api/users/${id}`, {
method: "PUT",
body: JSON.stringify(formValues),
});3. null、undefined、空字串要定義清楚
PATCH 時,這兩種語意可能不同:
{
"nickname": null
}和:
{}前者可能代表「清空 nickname」,後者代表「不更新 nickname」。
常見追問
POST 和 PUT 差在哪?
POST 常用來建立資源,資源 id 通常由 server 決定。PUT 常用來更新指定資源,URL 通常已經包含資源 id。
PATCH 一定不是 idempotent 嗎?
不一定。PATCH 是否 idempotent 取決於 patch 的語意。設定 name 通常是 idempotent;數量加一通常不是。
PUT 可以建立資源嗎?
可以,但通常是在 client 已經知道完整資源 URL 的情況,例如 PUT /files/avatar.png。一般 REST API 建立資料更常見是 POST /users。
面試回答模板
PUT 通常用來替換整份資源,request body 應該接近完整資源;PATCH 則用來局部更新,只送要修改的欄位。PUT 通常是 idempotent,PATCH 是否 idempotent 要看 patch 的語意,例如設定 name 是 idempotent,但 quantity 加一就不是。前端串接時我會特別確認漏欄位、null、undefined、空字串在後端代表什麼,避免不小心覆蓋資料。