编者注:==这份命名规范速查表==总结了前端开发中变量和函数命名的核心原则:1) 使用英语命名,保持一致性;2) 遵循 S-I-D 原则(简短、直观、描述性);3) 避免缩写和上下文重复;4) 函数命名采用 A/HC/LC 模式(动作+高上下文+低上下文)。特别强调了 ==get/set==、==remove/delete== 等动词的精确使用差异,以及 ==is/has/should== 等前缀的语义区分。
命名规范速查表
命名是困难的。本文档试图让它变得简单些。
虽然这些建议适用于任何编程语言,但我会用 JavaScript 来举例说明。
英语语言
使用英语命名变量和函数。
/* 错误示范 */
const primerNombre = "Gustavo";
const amigos = ["Kate", "John"];
/* 正确示范 */
const firstName = "Gustavo";
const friends = ["Kate", "John"];
无论喜欢与否,英语是编程中的主导语言:所有编程语言的语法都是用英语编写的,还有无数的文档和教育材料。用英语编写代码可以显著提高其内聚性。
命名规范
选择一种命名规范并遵循它。可以是 camelCase、PascalCase、snake_case 或其他任何形式,只要保持一致。许多编程语言对命名规范有自己的传统;请查阅你的语言文档或在 GitHub 上研究一些流行的仓库!
/* 错误示范 */
const page_count = 5;
const shouldUpdate = true;
/* 正确示范 */
const pageCount = 5;
const shouldUpdate = true;
/* 同样正确 */
const page_count = 5;
const should_update = true;
S-I-D原则
名称必须简短、直观和描述性:
- 简短:名称不应过长,便于输入和记忆;
- 直观:名称应尽可能接近日常用语;
- 描述性:名称应最有效地反映其功能/内容。
/* 错误示范 */
const a = 5; // "a" 可以表示任何东西
const isPaginatable = a > 10; // "Paginatable" 听起来极不自然
const shouldPaginatize = a > 10; // 编造动词很有趣!
/* 正确示范 */
const postCount = 5;
const hasPagination = postCount > 10;
const shouldPaginate = postCount > 10; // 替代方案
避免缩写
不要使用缩写。它们只会降低代码的可读性。找到一个简短、描述性的名称可能很难,但缩写不是借口。
/* 错误示范 */
const onItmClk = () => {};
/* 正确示范 */
const onItemClick = () => {};
避免上下文重复
名称不应重复定义它的上下文。如果不会降低可读性,总是从名称中移除上下文。
class MenuItem {
/* 方法名重复了上下文(即 "MenuItem") */
handleMenuItemClick = (event) => { ... }
/* 读起来很好,如 `MenuItem.handleClick()` */
handleClick = (event) => { ... }
}
反映预期结果
名称应反映预期结果。
/* 错误示范 */
const isEnabled = itemCount > 3;
return <Button disabled={!isEnabled} />;
/* 正确示范 */
const isDisabled = itemCount <= 3;
return <Button disabled={isDisabled} />;
函数命名
A/HC/LC模式
命名函数时有一个有用的模式:
前缀? + 动作 (A) + 高上下文 (HC) + 低上下文? (LC)
查看下表了解这个模式的应用:
| 名称 | 前缀 | 动作 (A) | 高上下文 (HC) | 低上下文 (LC) |
|---|---|---|---|---|
getUser | get | User | ||
getUserMessages | get | User | Messages | |
handleClickOutside | handle | Click | Outside | |
shouldDisplayMessage | should | Display | Message |
**注意:**上下文的顺序会影响变量的含义。例如,
shouldUpdateComponent表示_你_将要更新组件,而shouldComponentUpdate告诉你_组件_将更新自己,你只是控制_何时_更新。换句话说,高上下文强调变量的含义。
动作
函数名称的动词部分。最重要的部分,负责描述函数_做什么_。
get
立即访问数据(即内部数据的快捷获取器)。
function getFruitCount() {
return this.fruits.length;
}
另见 compose。
你也可以在异步操作中使用 get:
async function getUser(id) {
const user = await fetch(`/api/user/${id}`);
return user;
}
set
以声明式的方式设置变量,将值 A 设为值 B。
let fruits = 0;
function setFruits(nextFruits) {
fruits = nextFruits;
}
setFruits(5);
console.log(fruits); // 5
reset
将变量设置回其初始值或状态。
const initialFruits = 5;
let fruits = initialFruits;
setFruits(10);
console.log(fruits); // 10
function resetFruits() {
fruits = initialFruits;
}
resetFruits();
console.log(fruits); // 5
remove
从某处_移除_某物。
例如,如果你在搜索页面上有一组选定的过滤器,从集合中移除其中一个就是 removeFilter,不是 deleteFilter(这也是你在英语中自然表达的方式):
function removeFilter(filterName, filters) {
return filters.filter((name) => name !== filterName);
}
const selectedFilters = ["price", "availability", "size"];
removeFilter("price", selectedFilters);
另见 delete。
delete
完全从存在领域中擦除某物。
想象你是一个内容编辑,有一个你想摆脱的臭名昭著的帖子。一旦你点击了一个闪亮的"删除帖子"按钮,CMS 执行了一个 deletePost 动作,不是 removePost。
function deletePost(id) {
return database.find({ id }).delete();
}
另见 remove。
remove或delete?当
remove和delete的区别对你来说不太明显时,我建议看看它们的反义词 -add和create。add和create的关键区别在于add需要一个目的地,而create不需要目的地。你将一个项目add到某处,但你不"create它_到某处_"。 简单地将remove与add配对,delete与create配对。详细解释见这里。
compose
从现有数据创建新数据。主要适用于字符串、对象或函数。
function composePageUrl(pageName, pageId) {
return pageName.toLowerCase() + "-" + pageId;
}
另见 get。
handle
处理一个动作。常用于命名回调方法。
function handleLinkClick() {
console.log("点击了一个链接!");
}
link.addEventListener("click", handleLinkClick);
上下文
函数操作的领域。
函数通常是对_某物_的动作。说明其可操作领域或至少是预期的数据类型很重要。
/* 操作原始值的纯函数 */
function filter(list, predicate) {
return list.filter(predicate);
}
/* 专门操作帖子的函数 */
function getRecentPosts(posts) {
return filter(posts, (post) => post.date === Date.now());
}
一些特定语言的假设可能允许省略上下文。例如,在 JavaScript 中,
filter通常操作数组。添加显式的filterArray是不必要的。
前缀
前缀增强了变量的含义。在函数名称中很少使用。
is
描述当前上下文的特征或状态(通常是 boolean)。
const color = "blue";
const isBlue = color === "blue"; // 特征
const isPresent = true; // 状态
if (isBlue && isPresent) {
console.log("蓝色存在!");
}
has
描述当前上下文是否具有某个值或状态(通常是 boolean)。
/* 错误示范 */
const isProductsExist = productsCount > 0;
const areProductsPresent = productsCount > 0;
/* 正确示范 */
const hasProducts = productsCount > 0;
should
反映一个肯定的条件语句(通常是 boolean)与某个动作结合。
function shouldUpdateUrl(url, expectedUrl) {
return url !== expectedUrl;
}
min/max
表示最小或最大值。用于描述边界或限制。
/**
* 在给定的 min/max 边界内
* 渲染随机数量的帖子。
*/
function renderPosts(posts, minPosts, maxPosts) {
return posts.slice(0, randomBetween(minPosts, maxPosts));
}
prev/next
表示当前上下文中变量的前一个或下一个状态。用于描述状态转换。
async function getPosts() {
const prevPosts = this.state.posts;
const latestPosts = await fetch("...");
const nextPosts = concat(prevPosts, latestPosts);
this.setState({ posts: nextPosts });
}
单复数形式
像前缀一样,变量名可以根据它们是保存单个值还是多个值而变为单数或复数。
/* 错误示范 */
const friends = "Bob";
const friend = ["Bob", "Tony", "Tanya"];
/* 正确示范 */
const friend = "Bob";
const friends = ["Bob", "Tony", "Tanya"];
译者:Claude 3.5 Sonnet