Skip to content

代码结构

代码结构关注的不是某个 API,而是“JavaScript 代码本身是怎么组织和执行的”。这一层内容很基础,但会直接影响可读性、格式稳定性和很多看似奇怪的语法行为。

一段脚本由什么组成

可以先把 JavaScript 代码理解成由很多条语句组成:

js
const name = 'Lee'
console.log(name)

上面这两行就是两条独立语句。

日常写代码时,通常会把一条语句写成一行,这不是语法强制,而是为了让结构更清晰。

语句和表达式

表达式

表达式的特点是“会产生一个值”:

js
1 + 2
user.name
isLogin ? '退出' : '登录'

语句

语句的特点是“执行一个动作”:

js
if (isLogin) {
  console.log('welcome')
}

两者不完全对立,但理解这个区别有助于看懂:

  • 哪些位置要求写值
  • 哪些位置要求写动作
  • 为什么三元表达式和 if 适用场景不同

代码块

花括号 {} 可以把多条语句组织成一个代码块:

js
if (score >= 60) {
  console.log('pass')
  console.log('done')
}

代码块常见于:

  • 条件分支
  • 循环
  • 函数体
  • 单独的块级作用域
js
{
  const message = 'hello'
  console.log(message)
}

分号

JavaScript 支持显式写分号,也支持在很多情况下依赖自动分号插入。

js
const a = 1
const b = 2

这段代码即使没有分号,通常也能正常工作。

自动分号插入

JavaScript 会在某些位置自动补出分号,这套机制通常叫 ASI,也就是自动分号插入。

大多数时候它符合直觉,但并不是所有换行都能安全地被当作语句结束。

常见安全情况

js
console.log('hello')
console.log('world')

容易出问题的情况

某一行如果以下一个可继续拼接当前表达式的符号开头,就可能和上一行连在一起,例如:

js
console.log('hello')
;[1, 2, 3].forEach((item) => {
  console.log(item)
})

这里开头的分号就是为了显式切断上一条语句。

如果省略它,代码可能被解释成一条完全不同的表达式,进而报错或产生意外行为。

关于分号的实践建议

团队里通常会选择两种风格之一:

  • 始终写分号
  • 在格式化规则允许下大多数情况省略分号,但在特殊场景补上保护性分号

无论选哪种,最重要的是:

  • 在项目内保持一致
  • 遇到以 [(、模板字符串等开头的新语句时保持警惕

注释

注释用于解释意图、补充上下文和说明边界条件。

单行注释

js
// 只在开发环境输出日志
console.log('debug')

多行注释

js
/*
  这里处理的是首屏初始化逻辑,
  需要在 DOM 就绪后执行。
*/
boot()

注释的基本原则

注释应该解释“为什么”,而不是复述“做了什么”

不太有价值的注释:

js
const count = 1 // 把 1 赋值给 count

更有价值的注释:

js
// 这里保留 1 秒延迟,避免首屏骨架闪烁
setTimeout(render, 1000)

避免过期注释

如果代码已经改了,而注释没同步,错误注释往往比没注释更糟。

不要依赖嵌套块注释

JavaScript 不支持 /* ... */ 的嵌套:

js
/*
  /* nested */
*/

这类写法会直接破坏代码结构。

可读性的结构建议

  • 一条语句尽量只表达一层意思
  • 控制单行长度,复杂表达式适当换行
  • 代码块边界尽量清晰,不要把多个概念硬塞进一行
  • 格式统一交给格式化工具,减少人工风格分歧

基于 MIT 许可发布