关键字是 JavaScript 语法的骨架。
你写下的每一个
if、for、async、await、new、try,背后都对应着语言层面的固定规则。本文结合一份真实的聊天前端代码,系统梳理 JavaScript 常用关键字的用法、作用,以及容易混淆的保留字和上下文关键字。
一、先分清:关键字、保留字、上下文关键字、字面量
很多初学者会把下面这些东西统称为"关键字",其实它们并不完全一样。
| 类型 | 说明 | 例子 |
|---|---|---|
| 关键字 | 语法中有特殊意义,不能随便当变量名 | if、for、function、return、new |
| 保留字 | 当前可能没用到,但未来可能用,不能当标识符 | enum、implements、interface |
| 上下文关键字 | 只在特定语法位置特殊,其他位置可作普通标识符 | async、await、of、as、from、get、set |
| 字面量 | 表示固定值,不是关键字但语法特殊 | true、false、null |
| 全局属性 | 不是关键字,但通常不要用作变量名 | undefined、NaN、Infinity |
比如在这份聊天代码中:
js
let backendUrl = 'http://localhost:8088';
let token = '';
let currentUser = null;
let stompClient = null;
let sentMessageIds = new Set();
const AVATAR_GRADIENTS = [
'linear-gradient(135deg, #667eea, #764ba2)',
// ...
];
这里的 let、const、new、null 就是最常用的关键字和字面量。
二、声明与作用域:var、let、const
1. var
var 是早期 JavaScript 的变量声明方式。
特点:
- 函数作用域,不是块级作用域。
- 存在变量提升。
- 可以重复声明。
- 容易造成污染和意外覆盖。
现代代码中通常不再推荐使用 var。
js
var a = 1;
var a = 2; // 不报错
2. let
let 声明块级作用域变量,可以重新赋值。
特点:
- 块级作用域。
- 存在暂时性死区。
- 不允许在同一作用域重复声明。
在这份 IM 代码中,大量全局状态都用 let:
js
let backendUrl = 'http://localhost:8088';
let token = '';
let currentUser = null;
let stompClient = null;
let currentChat = null;
let friends = [];
let groups = [];
let pendingFriendRequests = [];
let activeTab = 'friends';
let groupSubscriptions = {};
let isLoggingOut = false;
let sentMessageIds = new Set();
这些变量在运行过程中会变化,所以用 let 合适。
3. const
const 声明块级常量。
特点:
- 必须初始化。
- 不能重新赋值。
- 但对象、数组内部内容可以修改。
- 适合 DOM 引用、配置、常量表。
代码中:
js
const AVATAR_GRADIENTS = [
'linear-gradient(135deg, #667eea, #764ba2)',
'linear-gradient(135deg, #f093fb, #f5576c)',
// ...
];
以及:
js
const lines = data.split('\n');
const command = lines[0];
const wsUrl = backendUrl.replace('http', 'ws') + '/api/ws';
这些变量一旦确定就不需要重新赋值,用 const 更安全。
小结
| 关键字 | 作用域 | 可否重复声明 | 可否重新赋值 | 建议 |
|---|---|---|---|---|
var |
函数作用域 | 可以 | 可以 | 少用 |
let |
块级作用域 | 不可以 | 可以 | 变量首选 |
const |
块级作用域 | 不可以 | 不可以 | 常量首选 |
三、函数与返回值:function、return
1. function
function 用于声明函数。
这份代码中定义了大量工具函数和业务函数:
js
function extractList(payload) {
if (Array.isArray(payload)) return payload;
if (!payload || typeof payload !== 'object') return [];
for (const key of ['records', 'content', 'items', 'list', 'data', 'rows']) {
if (Array.isArray(payload[key])) return payload[key];
}
return [];
}
js
function pickFriendId(f) {
if (!f || typeof f !== 'object') return null;
return f.friendId ?? f.friendUserId ?? f.userId ?? f.id ?? null;
}
js
async function api(path, options = {}) {
return fetch(`${backendUrl}/api${path}`, {
...options,
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
...options.headers
}
});
}
2. return
return 有两个作用:
- 返回函数结果。
- 提前结束函数。
例如:
js
function extractList(payload) {
if (Array.isArray(payload)) return payload;
if (!payload || typeof payload !== 'object') return [];
// ...
}
这里用 return 做"提前返回",避免层层嵌套。
四、异步编程:async、await
1. async
async 用于声明异步函数。
异步函数总是返回一个 Promise。
js
async function loadFriends() {
try {
const resp = await api('/friends');
const data = await resp.json();
friends = (data.code === 200) ? extractList(data.data) : [];
} catch (e) {
console.error('加载好友失败', e);
friends = [];
}
}
2. await
await 用于等待 Promise 结果。
它只能在 async 函数或 ES Module 顶层使用。
js
const resp = await api('/friends');
const data = await resp.json();
作用:把异步代码写成接近同步的风格,可读性更好。
在这份 IM 代码中,所有网络请求几乎都用了 async/await:
js
async function loadGroups() {
try {
const resp = await api('/groups');
const data = await resp.json();
groups = (data.code === 200) ? extractList(data.data) : [];
} catch (e) {
console.error('加载群组失败', e);
groups = [];
}
}
五、流程控制:if、else、switch、for、while、break
1. if 和 else
用于条件判断。
代码中到处都是:
js
if (!token) {
goToLoginView();
return;
}
if (localStorage.getItem('prefillAccount')) {
goToLoginView();
return;
}
js
if (data.code === 200 && data.data) {
// ...
} else {
// ...
}
2. switch、case、default
用于多分支判断。
这份代码中没有显式使用 switch,但下面这段很适合改写成 switch:
js
if (command === 'CONNECTED') {
subscribeStomp('/user/queue/chat');
if (currentChat && currentChat.type === 'group') subscribeGroup(currentChat.id);
} else if (command === 'MESSAGE') {
// ...
}
改写后:
js
switch (command) {
case 'CONNECTED':
// ...
break;
case 'MESSAGE':
// ...
break;
default:
break;
}
3. for 和 of
for...of 用于遍历可迭代对象,比如数组、Set、Map、字符串。
js
for (const key of ['records', 'content', 'items', 'list', 'data', 'rows']) {
if (Array.isArray(payload[key])) return payload[key];
}
这里的 of 是上下文关键字。
普通 for 循环:
js
for (let i = 0; i < s.length; i++) {
hash = (hash * 31 + s.charCodeAt(i)) | 0;
}
4. while
用于条件循环。
js
while (n >= 1024 && i < units.length - 1) {
n /= 1024;
i++;
}
5. break
用于跳出循环或 switch。
js
for (let i = 0; i < lines.length; i++) {
if (lines[i] === '') {
bodyStartIndex = i + 1;
break;
}
}
6. continue
用于跳过本次循环,进入下一次。本代码未使用。
六、异常处理:try、catch、finally、throw
1. try、catch、finally
用于捕获和处理异常。
代码中大量使用:
js
try {
const resp = await api('/users/me');
const data = await resp.json();
// ...
} catch (e) {
console.error('加载用户信息失败', e);
}
js
try {
// ...
} finally {
btn.disabled = false;
btn.textContent = '保存资料';
}
finally 中的代码无论是否发生异常都会执行,非常适合恢复按钮状态。
2. throw
用于主动抛出异常。本代码没有直接使用,但 try/catch 捕获的异常可能来自 fetch、JSON.parse 等。
js
throw new Error('something wrong');
七、对象、类型与实例:new、typeof、instanceof、in、delete
1. new
用于创建实例。
js
const ws = new WebSocket(wsUrl);
let sentMessageIds = new Set();
const date = new Date(timeStr);
const url = new URL(url);
2. typeof
用于判断类型。
js
if (!payload || typeof payload !== 'object') return [];
if (!avatar || typeof avatar !== 'string') {
renderAvatarFallback(containerEl, name);
return;
}
if (typeof target.focus === 'function') {
target.focus();
}
3. instanceof
用于判断对象是否为某个构造函数的实例。本代码未使用。
js
if (err instanceof Error) {
// ...
}
4. in
用于判断属性是否存在于对象中。本代码未使用。
js
if ('name' in user) {
// ...
}
5. delete
用于删除对象属性。
js
delete groupSubscriptions[groupId];
八、类与面向对象:class、extends、super、static、get、set
这份 IM 代码主要使用函数和对象,没有使用 class。
但现代 JavaScript 常用:
js
class User {
constructor(name) {
this.name = name;
}
say() {
console.log(this.name);
}
}
class Admin extends User {
constructor(name) {
super(name);
}
static create(name) {
return new Admin(name);
}
get label() {
return `Admin: ${this.name}`;
}
set label(value) {
this.name = value.replace('Admin: ', '');
}
}
相关关键字:
| 关键字 | 作用 |
|---|---|
class |
声明类 |
extends |
继承 |
super |
调用父类构造或方法 |
static |
静态成员 |
get |
getter |
set |
setter |
this |
当前实例上下文 |
九、模块相关:import、export、from、as、default
现代前端工程常用 ES Module:
js
import { createApp } from 'vue';
import App from './App.vue';
export default App;
export const version = '1.0.0';
| 关键字 | 作用 |
|---|---|
import |
导入模块 |
export |
导出模块 |
from |
指定模块来源 |
as |
重命名 |
default |
默认导出 |
这份 IM 代码没有使用模块语法,而是通过:
js
window.IMApp
window.electronAPI
进行集成。
十、字面量与特殊值:null、true、false、undefined
1. null
表示空值。
js
let currentUser = null;
let stompClient = null;
let currentChat = null;
let activeVideo = null;
2. true 和 false
布尔值。
js
let isLoggingOut = false;
let currentMuted = false;
js
vis.phone === true;
vis.address === true;
3. undefined
undefined 不是关键字,而是全局属性。
表示"未定义"。
js
let a;
console.log(a); // undefined
不要用 undefined 当变量名,虽然某些作用域下可以,但非常不推荐。
十一、完整关键字/保留字清单
常用关键字
text
break, case, catch, class, const, continue, debugger, default,
delete, do, else, export, extends, finally, for, function, if,
import, in, instanceof, let, new, return, super, switch, this,
throw, try, typeof, var, void, while, with, yield
异步与上下文关键字
text
async, await, of, as, from, get, set, static
字面量/特殊值
text
null, true, false
未来保留字
text
enum
严格模式保留字
text
implements, interface, package, private, protected, public, static, yield
历史保留字
text
abstract, boolean, byte, char, double, final, float, goto, int,
long, native, short, synchronized, throws, transient, volatile
不是关键字但常被误认为关键字
text
undefined, NaN, Infinity, arguments, eval, window, document
十二、结合 IM 代码的实战总结
| 关键字 | 代码示例 | 作用 |
|---|---|---|
let |
let token = ''; |
声明可变状态 |
const |
const AVATAR_GRADIENTS = [...] |
声明常量 |
function |
function extractList(payload) {} |
声明函数 |
return |
if (Array.isArray(payload)) return payload; |
返回结果/提前结束 |
if/else |
if (!token) { ... } else { ... } |
条件分支 |
for/of |
for (const key of [...]) |
遍历数组 |
while |
while (n >= 1024 && i < units.length - 1) |
循环换算 |
break |
if (lines[i] === '') { break; } |
跳出循环 |
try/catch/finally |
try { await api(...) } catch (e) {} |
异常处理 |
async/await |
const resp = await api('/friends'); |
异步请求 |
new |
new WebSocket(wsUrl) |
创建实例 |
typeof |
typeof payload !== 'object' |
类型判断 |
delete |
delete groupSubscriptions[groupId]; |
删除对象属性 |
null |
let currentUser = null; |
空值初始化 |
true/false |
let isLoggingOut = false; |
布尔状态 |
十三、结语
JavaScript 关键字并不只是"语法规定",它们决定了:
- 变量作用域:
var/let/const - 函数与异步:
function/async/await - 流程控制:
if/for/while/break - 异常处理:
try/catch/finally - 对象与实例:
new/this/typeof/delete - 模块化:
import/export - 面向对象:
class/extends/super
写现代 JavaScript 时,可以记住几个简单原则:
- 优先用
let和const,少用var。 - 异步请求用
async/await,并用try/catch/finally处理异常。 - 遍历数组用
for...of,遍历对象属性用for...in或Object.keys。 - 不要用保留字做变量名。
- 分清关键字、上下文关键字、字面量和全局属性。
掌握这些关键字,基本就掌握了 JavaScript 语法的骨架。