key、code、keyCode 差在哪?

三個屬性都掛在 keydown 與 keyup 事件上,回答的是三個不同的問題。同一顆 A 鍵,按法不同時三者的值是這樣:

 event.keyevent.codekeyCode
代表什麼這一下的字元或功能名稱實體按鍵的位置舊的數字代碼
跟著 Shift、配置、輸入法變嗎會不會部分會,各瀏覽器不一致
按 A 鍵aKeyA65
按住 Shift 再按 AAKeyA65
規格W3C UI Events KeyboardEvent key ValuesW3C UI Events KeyboardEvent code Values只剩 UI Events 規格的舊版相容章節

code 的名字是照美式鍵盤取的位置名稱,不是你鍵帽上印的字。MDN 的例子:在法文 AZERTY 鍵盤上按印著 A 的那顆鍵,code 是 KeyQ(它在美式鍵盤上是 Q 的位置),key 才是 a。所以要顯示「按了哪個字」給使用者看,用 key;要做「不管什麼配置,左手這四顆就是方向」的遊戲操作,用 code。

104 顆鍵的 keycode 對照表(點一下就複製)

下面分八組列出美式 104 鍵鍵盤的所有按鍵:包含本站鍵盤測試鍵盤圖上的鍵,以及圖上沒畫出的 Print Screen、Scroll Lock 與 Pause。key 是沒按修飾鍵時的值,「按住 Shift」是同一顆鍵按住 Shift 時的 key。keyCode 取 W3C UI Events 舊版相容章節的值,規格沒列的鍵取 MDN 對照表裡 Windows 版 Chrome 的值;跟它不同的瀏覽器與作業系統寫在同一格下面。

點表格裡任何一個值就會複製那個值;每組上方的按鈕會把整組複製成 TSV,可以直接貼進試算表。空白鍵的 key 是一個空白字元,表格與複製內容都加上引號才看得見。複製的 " " 已經是一個 JavaScript 字串,直接貼到 event.key === 後面就好,不用再加引號。

字母鍵 A 到 Z

key 是小寫字母,按住 Shift 時是大寫;code 是 Key 加大寫字母;keyCode 一律是大寫字母的 ASCII 碼,A 是 65、Z 是 90。

按鍵event.key按住 Shiftevent.codekeyCode
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z

數字鍵 0 到 9(主鍵盤上排)

code 是 Digit 加數字,keyCode 是數字的 ASCII 碼 48 到 57。數字鍵盤上的同一個數字 key 相同,但 code 與 keyCode 不同(見最後一組)。

按鍵event.key按住 Shiftevent.codekeyCode
1
2
3
4
5
6
7
8
9
0

Esc、F1 到 F12、Print Screen、Scroll Lock 與 Pause

F1 到 F12 的 key 與 code 都是 F 加數字,keyCode 是 112 到 123。筆電常要按住 Fn 才送得出 F 鍵,而 Fn 通常是硬體自己處理的鍵,不會另外送出代碼。

Print Screen、Scroll Lock 與 Pause 在 F12 右邊,code 規格也把它們跟 F 鍵歸在同一區。這三顆鍵的 key 和 code 名稱相同,keyCode 是 44、145、19。MDN 的表格提到兩個要注意的地方:Windows 上按 Print Screen 只會送出 keyup,不會有 keydown;Mac 會把 PC 鍵盤的這三顆鍵當成 F13、F14、F15,所以 Mac 版 Chrome 與 Safari 送出的是 124、125、126。本站的鍵盤圖沒畫出這三顆,按下後可以看「最近的瀏覽器事件」。

按鍵event.keyevent.codekeyCode
Esc
F1
F2
F3
F4
F5
F6
F7
F8
F9
F10
F11
F12
Print ScreenMac 版 Chrome 與 Safari:124;Linux 版 Chromium 與 Firefox:42
Scroll LockMac 版 Chrome 與 Safari:125
PauseMac 版 Chrome 與 Safari:126

修飾鍵:Shift、Ctrl、Alt、Windows 與 Command

左右兩顆的 key 相同,只有 code 分得出左右;keyCode 大多也不分左右,Windows 版 Chrome 的 Windows 鍵(91 與 92)是例外。Mac 的 Command 鍵是 Meta,Option 鍵是 Alt。不少非美式配置把右 Alt 當成 AltGr 用,這時它的 key 是 AltGraph。

按鍵event.keyevent.codekeyCode
左 Shift
右 Shift
左 Ctrl
右 Ctrl
左 Alt(Mac 是 Option)
右 Alt(Mac 是 Option)
左 Windows 鍵(Mac 是 Command)Mac 版 Firefox:224
右 Windows 鍵(Mac 是 Command)Mac 版 Chrome 與 Safari:93;Windows 與 Linux 版 Firefox:91;Mac 版 Firefox:224
Caps Lock

Enter、空白與編輯鍵

空白鍵的 key 是一個空白字元,不是 Space;Space 是它的 code。Mac 鍵盤上印 Return 的鍵,key 與 code 都是 Enter;主鍵盤區印 delete 的鍵,code 是 Backspace。

按鍵event.keyevent.codekeyCode
Backspace
Tab
Enter(Mac 是 Return)
空白鍵
Insert
Delete
選單鍵Mac 版 Chrome 與 Safari:0

方向與翻頁鍵

方向鍵的 key 與 code 同名,keyCode 是 37 到 40,順序是左、上、右、下。

按鍵event.keyevent.codekeyCode
上方向鍵 ↑
下方向鍵 ↓
左方向鍵 ←
右方向鍵 →
Home
End
Page Up
Page Down

標點符號鍵

標點的 key 看鍵盤配置,下表是美式配置。keyCode 在 Firefox 有三顆不一樣:分號是 59、等號是 61、減號是 173。

按鍵event.key按住 Shiftevent.codekeyCode
` ~
- _Firefox:173
= +Firefox:61
[ {
] }
\ |
; :Firefox:59
' "
, <
. >
/ ?

數字鍵盤

數字鍵盤的 key 跟上排數字一樣是 1,只有 code(Numpad1)分得出來,keyCode 是 96 到 105。下表是 NumLock 開著的值。Mac 鍵盤的數字鍵盤在這個位置是 Clear 鍵,規格要它送出的 code 一樣是 NumLock。

按鍵event.keyevent.codekeyCode
Num LockMac:12
數字鍵盤 /
數字鍵盤 *
數字鍵盤 -
數字鍵盤 +
數字鍵盤 Enter
數字鍵盤 .
數字鍵盤 0
數字鍵盤 1
數字鍵盤 2
數字鍵盤 3
數字鍵盤 4
數字鍵盤 5
數字鍵盤 6
數字鍵盤 7
數字鍵盤 8
數字鍵盤 9

NumLock 關掉時,同一顆鍵的 code 不變,key 與 keyCode 換成它印的第二個功能:1 是 End(35)、2 是 ArrowDown(40)、0 是 Insert(45)、小數點是 Delete(46)。

同一顆鍵,key 為什麼會不一樣?

  • Shift:MDN 的例子是按住 Shift 再按 2,美式配置的 key 是 @,英式配置是 ",code 兩邊都是 Digit2。
  • 鍵盤配置:AZERTY、德文 QWERTZ 這類配置會換掉某些位置上的字,key 跟著變、code 不變。
  • 輸入法:用注音、倉頡等輸入法組字時,組字期間的按鍵事件 event.isComposing 是 true,keydown 的 keyCode 是 229(W3C UI Events)。
  • 系統先接走的鍵:Fn、Alt+Tab、Cmd+Tab 與瀏覽器保留的快捷鍵(例如 Ctrl+W)會先被作業系統或瀏覽器處理,本站的鍵盤測試也收不到這些事件。

輸入法這一條最常踩到:在輸入框按 Enter 選字,程式卻把它當成「送出」。MDN 建議兩個條件都檢查,因為開始與結束組字的那一下,isComposing 可能還是 false,keyCode 卻已經是 229:

input.addEventListener('keydown', (event) => {
  // 注音、倉頡等輸入法還在組字,這一下是選字用的,先略過
  if (event.isComposing || event.keyCode === 229) return
  if (event.key === 'Enter') submit()
})

keyCode 已經棄用,要改用什麼?

MDN 把 keyCode 標成已棄用,建議改用 code(實體按鍵)或 key(按鍵對應的字元)。改寫舊程式時先想清楚你在意的是哪一個:

// 舊寫法:keyCode 已棄用
if (event.keyCode === 13) submit()

// 在意「按了什麼功能」:用 key,主鍵盤與數字鍵盤的 Enter 都會進來
if (event.key === 'Enter') submit()

// 在意「按了哪個位置」:用 code,換成 AZERTY 鍵盤也還是同一顆
if (event.code === 'KeyW') moveForward()

改寫時留意兩件事。第一,key 分不出主鍵盤與數字鍵盤,兩顆 Enter 的 key 都是 Enter,code 才分得出 Enter 與 NumpadEnter。第二,舊程式或舊資料裡的 OSLeft、OSRight 是 Windows 鍵的舊 code,MDN 記錄 Firefox 118 與 Chrome 52 以前的版本用這個名字,現在是 MetaLeft、MetaRight。

用鍵盤測試查任何一顆鍵

表格是規格與文件寫的值;你的鍵盤、配置與瀏覽器實際送出什麼,打開鍵盤測試按一次最準:

  1. 點一下鍵盤圖(或用 Tab 移進測試區),狀態列出現「正在接收鍵盤事件」。
  2. 按下你要查的鍵。「最後一個按下的鍵」大字是 key,底下那行是 code,鍵盤圖上那一格同時亮起來。
  3. 往下看「最近的瀏覽器事件」,每一下的 keydown、keyup 都列出 key、code 與按住的修飾鍵。查完按 Esc 離開測試區。
鍵盤測試按住 Shift 再按 2 的畫面:最後一個按下的鍵顯示 @,底下是 Digit2,修飾鍵顯示 Shift,鍵盤圖上的左 Shift 與 2 亮起
按住 Shift 再按 2(程式送出的按鍵):key 是 @、code 是 Digit2,修飾鍵顯示 Shift。本工具只顯示 key 與 code,不顯示已棄用的 keyCode。