命名风格与罗马数字速查表

变量该用 camelCase 还是 snake_case?URL 该用连字符还是下划线?1999 的罗马数字怎么写?本页把 8 种命名风格的规则与适用场景列成对照表,并附罗马数字的基本符号与左减规则。

原理解析

命名规范约定标识符的大小写与分隔方式:camelCase(首词小写,如 userName)、PascalCase(每词首大写,如 UserName)、snake_case(下划线,如 user_name)、kebab-case(连字符,如 user-name)。

选哪种取决于语言与场景:JS/Java 变量用 camelCase、类用 PascalCase;Python 变量/函数用 snake_case;SQL 表/列多用 snake_case;URL 与 CSS 类多用 kebab-case。团队内保持一致比「哪种最好」更重要。

什么时候该查这张表

这张表在你要给变量、函数、文件、API 字段统一命名风格时有用。它把 camelCase、PascalCase、snake_case、kebab-case、SCREAMING_SNAKE、Train-Case 等风格的构成规则与常见用途并列。命名是跨工具、跨团队协作的接口,风格统一的价值大于个人偏好。

不该查的情况:你在设计一套完整的命名规范体系并需要考虑语言生态差异(如 Go 的导出规则、Rust 的所有权命名约定、各语言的保留字)。本表给的是通用风格与主流约定,不含语言特例。

判断标准:看命名对象的作用域。同一模块内、私有、作用域小 → 短且随意;跨模块导出、成为公共 API → 必须严格遵循该语言的标准风格。判断标准很简单:如果这个名称会出现在别人写的代码里,就按语言规范来;如果只是内部变量,用团队习惯即可。

特别注意命名转换在不同语言里的语义差异:snake_case 在 Python 里是社区习惯但不是强制的,PEP 8 允许;Go 的 MixedCaps 是官方不推荐的(应写 MixedCaps 而非 mixed_Caps);而 JavaScript 生态里 camelCase 才是事实标准,用 snake_case 会被认为不符合惯例。

边界与常见陷阱

  • 跨语言传输时命名风格必须显式转换

    很多系统里同一份数据会经过多语言:数据库用 snake_case、Python 内部也用 snake_case、HTTP API 返回 camelCase、前端用 camelCase。如果靠「约定」而不是显式转换,就会出现两种错误:漏转换导致前端拿到 snake_case 字段,或者重复转换导致过度加下划线。规范做法是边界处显式映射(API 层用 alias / 序列化配置),并用测试锁定字段名。

  • 转换库对首字母缩写与大写的处理各不相同

    「HTTPServer」转成 snake_case,不同库会给出三种结果:HTTPServer(保持原样)、httpserver(全小写)、http_server(正确)。给 kebab-case 也一样:HTMLParser 可能变成 htmlparser、html-parser 或HTML-parser。这些名字往往会进入 URL、文件名或数据库列名,一旦上线就很难改。做法:关键名称用显式映射表,并对转换结果做快照测试;不要依赖库的自动推断。

  • 布尔值与复数的命名直接影响代码可读性

    布尔值用 「is」/「has」/「can」/「should」 前缀能立刻区分于值类型,避免 「if (enabled)」 与 「if (enabled === ‘yes’)」 这类误用。数组与集合用复数名词(items、tags),单个元素用单数(item、tag)—— 这个约定一旦破坏,读代码时就要反复回溯。另外避免用 「data」、「info」、「obj」 这类无信息量的名字,它们在搜索与调试时毫无区分度。

与相邻内容的分工

要检查某个名称在具体语言里的保留字冲突,属该语言文档范畴,本表不覆盖。

要处理文件名、URL 路径的批量转换,属工程脚手架范畴;本表给的是风格判断而非转换实现。

要设计 API 的字段命名与版本兼容策略,属接口设计范畴,需要先定协议再定风格。

若目的是解决团队命名混乱,先统一「作用域规则」(内部随意 / 导出严格)比先统一具体风格更有效。

实战片段

要点:① 按作用域决定严格程度 —— 会出现在别人代码里的导出名必须严格遵循语言标准,内部变量可用团队习惯;② 转换库对缩写与连续大写的处理各不相同(同一个 HTTPServer 会得到 3 种结果),关键名称用显式映射表 + 快照测试,不要依赖自动推断;③ 布尔值一律用 is/has/can/should 前缀,集合用复数名词、单个元素用单数;④ 避免 data/info/obj 这类零信息量命名;⑤ 跨语言/跨层边界必须显式做命名转换并用测试锁定字段名,靠约定迟早会漏。

// ① 常见风格的构成规则(正则可直接用于校验)
const STYLES = {
  camelCase:    /^[a-z][a-zA-Z0-9]*$/,        // myVariable
  PascalCase:   /^[A-Z][a-zA-Z0-9]*$/,        // MyVariable
  snake_case:   /^[a-z][a-z0-9_]*$/,          // my_variable
  kebab_case:   /^[a-z][a-z0-9-]*$/,          // my-variable
  SCREAMING:    /^[A-Z][A-Z0-9_]*$/,          // MY_VARIABLE
}

// ② 按作用域决定严格程度
function checkName(name, scope) {
  const ok = Object.entries(STYLES).find(([, re]) => re.test(name))
  return {
    valid: !!ok,
    style: ok ? ok[0] : null,
    // 导出的名字必须是语言标准风格,内部变量可放宽
    enforced: scope === 'export' ? ['camelCase', 'PascalCase'] : Object.keys(STYLES),
  }
}
console.log(checkName('myVar', 'export'))      // { valid: true, style: 'camelCase' }
console.log(checkName('my_var', 'export'))     // 导出命名不合 JS 惯例

// ③ 🔴 转换库对缩写/大写的处理各不相同 ⇒ 关键名称用显式映射
const EXPLICIT = { HTTPServer: 'http_server', XMLHttpRequest: 'xml_http_request' }
function toSnake(name) {
  if (EXPLICIT[name]) return EXPLICIT[name]          // 优先查表
  return name
    .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
    .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2')       // HTTPServer → HTTP_Server
    .toLowerCase()
}
console.log(toSnake('HTTPServer'))       // http_server(表命中)
console.log(toSnake('parseUserName'))    // parse_user_name

// ④ 布尔用前缀,集合用复数 —— 提升可读性
function describe(order) {
  return {
    isPaid:    order.status === 'paid',   // 布尔一律 is/has/can/should
    hasItems:  order.items.length > 0,
    items:     order.items,               // 集合用复数
    firstItem: order.items[0],            // 单个用单数
  }
}

// ⑤ 避免零信息量命名
const BAD  = { data: 1, info: 2, obj: 3, temp: 4 }
const GOOD = { userProfile: 1, requestHeaders: 2, httpResponse: 3, retryCount: 4 }

// ⑥ 跨语言边界显式转换(API 层 camelCase ↔ DB 层 snake_case)
const toCamel = s => s.replace(/_([a-z])/g, (_, c) => c.toUpperCase())
const toSnakeKey = s => s.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase()
console.log(toCamel('user_id'))          // userId
console.log(toSnakeKey('userId'))        // user_id

实践注解

  • camelCase 与 snake_case 的转换在缩写词上会翻车XMLHttpRequest 转成 snake_case 时是 xml_http_request 还是 x_m_l_http_request,取决于实现。跨语言边界(如 JSON 到 Python)做自动改名时,缩写与数字边界必须先写测试锁定,否则会出现静默的字段名不匹配。
  • URL 与文件系统惯例是小写加连字符大写字母在 URL 中会带来大小写敏感问题(Linux 服务器区分、CDN 缓存可能不区分),用 kebab-case 并全小写能规避;同时避免用下划线,因为部分 Markdown 渲染会把 a_b 解析成斜体。
  • 罗马数字的左减规则只覆盖六种组合只有 IV、IX、XL、XC、CD、CM 是合法的减法写法,IL 或 IC 都不是标准写法。做转换器时若允许任意「小在大前」,会产出 49 写成 IL 这类不合法结果。

数据来源

  • Language style guides
  • Unicode Roman numerals (U+2160–U+2188)

上述编号、名称与定义均来自公开规范,本站不主张对规范数据本身的独创性;本页的编排方式、中文释义与实践注解由本站撰写。

8 种命名风格对照

风格示例构成规则常见用途
camelCaseuserNameList首词全小写,后续词首字母大写JavaScript / Java 变量与函数名
PascalCaseUserNameList每个词首字母都大写类名、组件名、类型名
snake_caseuser_name_list全小写,词间下划线Python / Ruby 变量,数据库字段名
SCREAMING_SNAKEUSER_NAME_LIST全大写,词间下划线常量、环境变量
kebab-caseuser-name-list全小写,词间连字符URL 路径、CSS 类名、npm 包名
Train-CaseUser-Name-List首字母大写,词间连字符HTTP 头部名称、标题化标识
flatcaseusernamelist全小写且无分隔符包名、部分域名与命令行参数
dot.caseuser.name.list全小写,词间点号配置键、遥测指标名

罗马数字基本符号与左减规则

基本符号只有七个:I(1) V(5) X(10) L(50) C(100) D(500) M(1000)。小符号在大符号左边表示相减,右边表示相加。

数值罗马数字说明
1I基本符号
4IV左减:5 减 1
5V基本符号
9IX左减:10 减 1
10X基本符号
40XL左减:50 减 10
50L基本符号
90XC左减:100 减 10
100C基本符号
400CD左减:500 减 100
500D基本符号
900CM左减:1000 减 100
1000M基本符号

常见问题

camelCase 和 snake_case 到底该选哪个?

没有全局最优,跟随你所在语言与社区的既有约定最重要。Python、Ruby、Rust 惯用 snake_case,JavaScript、Java、Swift 惯用 camelCase,Go 则用 PascalCase 表示导出标识符。数据库列名普遍用 snake_case,因为多数数据库对大小写不敏感。真正的红线是同一个项目里不要混用:一旦混用,代码搜索、重构和自动化工具都会变得不可靠。跨系统边界时(比如后端 Python 返回给前端 JavaScript),在边界处做一次统一转换,而不是让两种风格渗进同一层。

URL 里为什么推荐 kebab-case 而不是下划线?

有三个实际原因。第一,搜索引擎传统上把连字符当作分词符,而下划线会被忽略,kebab-case 更利于关键词识别。第二,下划线在带下划线的超链接样式下会被下划线本身盖住,可读性变差。第三,URL 对大小写敏感,全小写能避免同一资源出现多个大小写变体造成的重复内容问题。综合起来,kebab-case 全小写是 URL 路径的事实标准。

罗马数字 4 为什么写成 IV 而不是 IIII?

罗马数字用「左减右加」的记数规则:小符号写在大符号左边表示相减,写在右边表示相加。所以 4 写成 IV 即 5 减 1,6 写成 VI 即 5 加 1。这条规则让写法更短也更易读。不过历史上确实存在 IIII 的写法,尤其在钟表面上,据说是为了视觉上与对面的 VIII 平衡,也避免 IV 被误读为罗马主神朱庇特的名字缩写。现代标准取 IV。

1999 用罗马数字怎么写?

写作 MCMXCIX,拆开看是 1000 + 900 + 90 + 9。逐段转换:1000 是 M;900 是 CM(1000 减 100);90 是 XC(100 减 10);9 是 IX(10 减 1)。拼接起来即 MCMXCIX。转换的通用做法是从大到小逐位取最大符号,遇到 4 和 9 这类数字时改用左减形式,而不是连续写四个相同符号。