JavaScript开发人员的清洁代码指南
每天,我代码查看数百行代码。全新的微服务,新功能,重构,固定固定等。我看过很多不同的编码口味,好坏的编码习惯等。
以下是我在行业中学到的十多年的所有知识。
一件事原理1
编写功能时,请提醒自己(理想情况下)只能做一件(简单)的事情。考虑一下您已经学到了有关评论的知识。代码应该说明一切。不需要评论。将代码分为小的可读函数,并且代码的可重复使用部分将使您的代码可读,并消除复制/粘贴相同代码的必要性,因为它没有正确地移动到可重复使用的功能/类中。
- 不可读功能
function retrieveName(user) {
if (user.name && user.name !=== 'admin' && user.name.length >= 5) {
return user.name;
}
// ...
}
一件事。整洁和清洁
const isRegularUser = (name) => {
return name !=== config.ADMIN_USERNAME;
}
const isValidNameLength = (name, minimumLength = 5) => {
return name.length >= minimumLength;
}
const isEligibleName(name) {
return isRegularUser(name) && isValidNameLength(name);
}
// …
function retrieveName(user) {
const name = user?.name;
if (isEligibleName(name)) {
return user.name;
}
}
不评论它的作用 - 写它做什么
用简单明了的单词命名您的函数和变量至关重要
如果代码需要太多的注释才能理解,则意味着需要重新制定代码。必须通过阅读代码来理解该代码。不是通过阅读评论。编写测试时也适用。必须证明代码的合理性通常是代码气味的不良迹象。
您的代码必须是您的评论。归根结底,作为开发人员,我们倾向于懒惰,并且不阅读评论(仔细)。但是,代码,我们总是这样做。
锦上添花,它总是更有意义,需要更少的时间来编写自我描述的代码而不是对其进行评论。
不好的做法
let validName = false;
// We check if name is valid by checking its length
if (name.length >= 3 && name.length <= 20) {
validName = true;
// Now we know that the name is valid
// …
}
const sr = 8.79; // Saving Rate
很好的例子
const isValidName = (name) => {
return (
name.length >= config.name.minimum && name.length <= config.name.maximum
);
};
// …
if (isValidName('Peter')) {
// Valid ✅
}
const savingRate = 8.79;
记住,您的工作是编写高效且有意义的代码,而不是无尽的评论。
船锚(又名Tree Shakingð³)
永远不要保留一些未使用的代码或评论代码,以防万一出于历史原因。
可悲的是,在拉的请求中找到注释的代码仍然很常见。
如今,每个人都使用诸如git之类的版本控制系统,因此,总有一个历史记录,您可以在需要时向后看。
保持未使用的代码的缺点
- 我们认为当它的时间时,我们会回来删除它。我们很可能会忙于其他事情,我们会忘记删除它。
- 未使用的代码将为以后的重构增加更多的复杂性。
- 即使未使用,在我们的代码库中搜索时仍会出现它(这也增加了复杂性)。
- 对于加入该项目的新开发人员,他们不知道他们是否可以删除它。
采取行动
在您的项目级别上添加Bitbucket/github管道或git挂钩,以拒绝任何未使用,死亡和注释的代码。
极简主义代码
以简约的方式编码是您可以遵循的最佳模式!对复杂性的简单性总是会获胜! ð
每次您需要创建新功能或在项目中添加一些内容时,请查看如何减少代码量。
有很多方法可以实现解决方案。而且总是有一个缩短,更干净的版本,应该始终是所选的版本。
开始编写代码之前三思而后行。问问自己我能写的最简单,最优雅的解决方案是什么,以便随着时间的流逝,书面代码可以很好地维护,并且很容易被其他不愿意的开发人员理解t有上下文/接受标准。
关于它的集思广益。稍后,您将在编写代码时节省更多的时间。
你不需要它(yagni)
不要代码,以防万一 '可能需要它。
不要花时间和资源在您可能不需要的东西上。
您今天需要解决今天的问题,明天的明天问题。
通过将它们包装到小型NPM库中,将代码重复使用您的代码
错误的方法
我的项目很小(嗯,总是很小)。
我不想花时间将功能分成分离的包裹。后来,我的项目确实变得越来越大。但是,由于我一开始就花时间将代码分成包装。现在,我认为将代码重构为可重复使用的软件包需要更长的时间。
简而言之,我是陷阱。我的体系结构只是不可扩展的。
正确的方法
总是考虑可重复性。无论您的项目有多小或大。
从长远来看,将代码分成可重复使用的外部软件包将始终加快您的速度。例如,有时候您将需要在另一个客户应用程序中使用一个非常相似的功能。
无论您是从头开始构建一个新项目还是在其中实施新功能,请始终考虑将代码提早分为可重复使用的内部NPM软件包,因此其他潜在产品将能够从中受益,并且不会重新发明轮子。
此外,由于重复使用相同的软件包,您的代码将获得一致性。
最后,如果需要改进或错误修复,您将只需更改一个位置(软件包),而不是每个受影响的项目。
锦上添花,您可以在GitHub和其他在线代码存储库上公开一些包裹,以获取一些免费的营销覆盖范围,并可能是您的图书馆和贡献者的一些好用户。 /p>
ð测试首先。从来没有最后
永远不要等到最后一刻添加一些单位测试,以了解您添加的最近更改。
太多的开发人员低估了开发阶段的测试。
不要在没有单位测试的情况下创建拉动请求。审查您的PR的其他开发人员不仅在审查您的更改,还包括您的测试。
此外,如果没有单元测试,您就不知道是否引入了新错误。您的新更改可能无法正常工作。
最后,如果您将测试推迟以后,您会不会有时间或急于写测试。
停止这样做
停止忽略单位测试的重要性。从长远来看,测试可以帮助您更快地开发。
开始做
甚至在更改代码之前创建测试。创建或更新当前测试,以期期望您将在代码库中引入新行为。您的测试将失败。然后,使用所需的更改更新项目的src
。
最后,进行单元测试。如果更改正确并且您的测试正确编写,那么您的测试现在应该通过ð完成!您现在正在遵循TDD开发方法ð
记住,有单位测试可以节省您的一天ð
仅导入您需要的东西
有一个很好的做法,就是仅导入所需的功能/变量。这将防止函数/可变冲突,但也仅通过公开所需的功能来优化您的代码/提高可读性。
- 导入一切
import _ from 'lodash';
// …
if (_.isEmpty(something)) {
_.upperFirst(something);
}
仅导入所需的
import { isEmpty as _isEmpty, upperFirst as _upperFirst } from 'lodash';
// …
if (_isEmpty(something)) {
_upperFirst(something);
}
条件清晰的功能名称
不可读条件
const { active, feature, setting } = qrCodeData;
if (active && feature === 'visitor' && setting.name.length > 0) {
// …
}
这种情况并不容易阅读,很长,不可重复使用,很可能也需要记录(使整个编码体验变得乏味)。
清晰的布尔功能
const canQrCode = ({ active, feature, setting }, featureName) => {
return active && feature === 'visitor' && setting.name.length > 0;
};
// …
if (canQrCode(qrCodeData, 'visitor')) {
// …
}
在这里,代码不需要评论。布尔条件功能确切地说明了它的作用,生成了可读和干净的代码ð
ð°樱桃在蛋糕上,代码可扩展。实际上,函数canQrCode
可以放置在服务或助手中,增加可重复性并减少复制代码的机会。
可读名称:变量
提及变量的清晰和明确的名称对于防止混乱至关重要。有时,我们花更多的时间了解变量应该包含的内容而不是完成给定的任务。
不良变量名称
// `nbPages` naming doesn’t mean much ❌
const nbPages = postService.getAllItems();
let res = '';
for (let i = 1; i <= nbPages; i++) {
res += '<a href="?page=' + i + '">' + i + '</a>';
}
}
给予i
以增量变量的名称是一个可怕的想法。虽然,这是显示for
循环示例的标准,但您绝不应该对生产应用程序做同样的事情(可悲的是,很多开发人员只需重复他们学到的东西。当然,我们可以怪他们,但是现在是时候改变了!)
每当您声明一个新变量时,请查看可以用来描述其存储内容的最佳和简短单词。
很好的例子,具有清晰的变量名称
// `totalItems` is a much better name ✅
const totalItems = postService.getAllItems();
// …
let htmlPaginationLink = '';
for (let currentPage = 1; currentPage <= totalItems; currentPage++) {
htmlPaginationLink +=
'<a href="?page=' + currentPage + '">' + currentPage + '</a>';
}
可读名称:功能
复杂(模糊/不清楚)功能名称
function cleaning(url) {
// …
}
明确的描述性名称
function removeSpecialCharactersUrl(url) {
// …
}
函数名称的每个单词都应大写,除了函数的第一个字母。这被称为 lowercamel 案例,例如isNameValid()
。
可读名称:类
通用/模糊的名称
class Helper { // 'Helper' doesn't mean anything
stripUrl(url) {
// ...
return url.replace('&', '');
}
// ...
}
班级名称含糊不清,并且没有清楚地传达其所作所为。通过阅读名称,我们对Helper
的包含以及如何使用它没有清晰的了解。
清晰/明确的名称
class Sanitizer { // <- Name is already more explicit
constructor(value) {
this.value = value;
}
url() {
this.value.replace('&', '');
// ...
}
}
在这种情况下,班级名称清楚地说明了它的作用。这是黑匣子的对立面。通过说什么,它也应该遵循仅实现一个目的的单一责任原则。
班级名称应该是一个(单数)名词,从大写字母开始。该课程还可以包含多个名词。如果是这样,每个单词都必须大写(这称为 uppercamel 案例)。
失败快速原则
在代码中应用 fail-fast 原理时,您将在出现问题时立即throw
或trigger
trigger
a exception
,而不是试图以不稳定的状态进行。此外,当功能指令fails early时,您将让应用程序体系结构的其他层/层知道有关在使用软件的高级组件之前首先要处理的错误。
后卫条款接近
从前面看到的失败原理得出,后卫条款技术是通过在return
语句之后删除冗余的else {}
块来提早离开函数的方式。
让我们看到一个不遵循后卫子句模式的片段,也可以是一个干净可读的示例。
两个样品代表函数的主体。在功能中,我们有以下ð
不可读的方式
if (payment.bonus) {
// … some logics
if (payment.bonus.voucher) {
return true; // eligible to a discount
} else if (payment.confirmed) {
if (payment.bonus.referral === 'friend') {
return true;
} else {
return false;
}
}
return false;
}
干净可读的方式
if (!payment.bonus) {
return false;
}
if (payment.bonus.voucher) {
return true;
}
if (payment.bonus.referral === 'friend') {
return true;
}
return false;
在此示例上,我们可以注意到如何通过return
语句尽早退出复杂的嵌套条件。
。
当您要分发库时,您应该在项目中始终创建一个.gitignore
和.gitattributes
,以防止在那里显示不良文件。
.gitignore
提交文件后,您的项目就需要一个.gitignore
文件。它保证将特定文件排除在您的代码库中。
冷13
当您发布依赖管理器使用的软件包时,至关重要的是排除开发文件(例如tests
文件夹,.github
配置文件夹,CONTRIBUTING.md
,SECURITY.me
,SECURITY.me
,.gitignore
,.gitattributes
,.gitattributes
本身,等等,等等。 )。
实际上,当您通过您喜欢的软件包管理器(NPM,Yarn,â)安装新软件包时,您只想下载所需的源文件,这是所有的,而无需包括测试文件,管道配置文件等,生产不需要。
Demeter Law
demeter Law ,又称最少知识的原则指出,每个代码的每个单位只能对其他代码单位具有非常有限的知识。他们只能与亲密的朋友交谈,而不是与陌生人ððð应该对其操纵对象的内部细节有任何了解。
链方法
object.doA()?.doB()?.doC(); // violated deleter’s law
在这里,doB
和doC
可能会从其子链功能中获得副作用。
非链式版本
object.doA();
object.doB();
object.doC();
每种方法都不依赖于彼此。它们是独立的,可以防止最终重构。
有效调试
在使用数组或对象调试时,使用console.table()
Koured26
console.log
使结果更难阅读。您应该始终瞄准最有效的选择。
const favoriteFruits = ['apple', 'bananas', 'pears'];
console.log(favoriteFruits);
â
console.table(array)
使用console.table
节省了时间,因为结果显示在清晰的表中,可提高调试数组或对象时日志的可读性。
Mozilla给我们一个明确的例子,看看console.table
如何帮助您。
const favoriteFruits = ['apple', 'bananas', 'pears'];
console.table(favoriteFruits);
更少的论点更有效
如果您的功能有3个以上的参数,则意味着您可以编写一个更好,更清洁的代码。简而言之,您的功能的目的太多了,违反了单一责任原则,导致调试和可重复使用。
简而言之,您的函数的参数越少,它将变得越有效,因为您将防止代码中的复杂性。
不干净的代码
function readItem(
id: number,
userModel: UserModel,
siteInfoModel: SiteModel,
security: SecurityCheck
) {}
干净的代码
user = new User(id);
// …
function readItem(user: User) {}
使用此版本,因为它只有相关的参数,因此在其他地方重复使用该函数,因为该函数不依赖或依赖不必要的参数/对象。
存根/仅您需要的东西
当您将对象固执在测试中(例如用Sinon)时,仅决定需要固执的功能,而不是将Entier对象置于启动。这样做,您还可以防止在业务逻辑中导致各种矛盾的功能的内部实现。
一切都是固定的
sinon.stub(myObject);
•只有您需要的功能是固定的
sinon.stub(myObject, 'myNeededFunction');
在这里,我们只掩盖了我们需要的个体功能。
删除多余的东西
当我们编码时,我们通常倾向于写“不必要的”内容,这也不会增加代码的可读性。
例如,在交换机中,没有使用的default
子句。
冗余版本
const PRINT_ACTION = 'print';
const RETURN_ACTION = 'return';
// …
switch (action) {
case PRINT_ACTION:
console.log(message);
break;
case RETURN_ACTION:
return message;
break; // ❌ This is redundant as we already exit the `switch` with `return`
default: // ❌ This clause is redundant
break;
}
整洁版本
const PRINT_ACTION = 'print';
const RETURN_ACTION = 'return';
// …
switch (action) {
case PRINT_ACTION:
console.log(message);
break;
case RETURN_ACTION:
return message;
default:
throw new Error(`Invalid ${action}`);
}
在这里,我们保留default
条款,但是我们通过抛出例外来从中受益。
自我是你的敌人
我经常看到开发人员亲自对他们的拉请求发表评论,因为他们将自己所做的事情视为自己的创作。当您收到变更请求时,不要感到被判断!这实际上是对自己的改进奖励ð
如果您想成为一个好的开发人员,请将您的自我留在壁橱里。永远不要把它上班。这只会减慢您的发展,甚至可能污染您的大脑空间和公司文化。
•别人说的话
将每一个反馈视为学习经历
编写代码时,这不是您的代码,它是每个人的代码。不要亲自撰写的内容。这只是整个船只的一小部分。
不使用缩写ð
缩写很难理解。对于熟悉公司条款的新细木工。即使有了普通的英语缩写,非母语说话者也可能很难理解,他们可能会在将来雇用或将开发人员从海外雇用。
。将永远不会在代码库中使用缩写的黄金法则(至少,您永远不必在此主题上做出任何进一步的决定)对于防止后来的混乱至关重要。
很难阅读。随着时间的流逝很难记住
if (type === Type.PPL_CTRL) {
// We are on People Controller
// Logic comes here
}
if (type === Type.PPL_ACT) {
// We are on People Action
// …
}
if (type === Type.MSG_DMN_EVT) {
// We are on Messaging Domain Event
// …
}
// ...
const IndexFn = () => {
// index function
}
清晰的名称(无需评论ð)
if (type === Type.PEOPLE_CONTROLLER) {
// Logic comes here
}
if (type === Type.PEOPLE_ACTION) {
// Logic here
}
if (type === Type.MESSAGING_DOMAIN) {
// Logic here
}
// ...
const index = () => {
// No need to have `Fn` or ˋFunction` as suffix in the name
// Having ˋfunction` or ˋmethod` for an actual function is redundant and generally bad practice
// ...
}
美国英语拼写。编码时的默认选择
我总是建议您在代码中仅使用 US English 。如果您同时将英国拼写混合在一起,它将引入某种混乱,以便以后引起一些混乱,并可能会对加入软件开发的新开发人员进行审讯。
大多数第三方图书馆和JavaScript的保留词都用美国英语编写。当我们在代码库中使用它们时,我们应该在代码中优先考虑我们的英语。 最后,我注意到,用英国拼写误解单词更容易,例如打字“ colur”而不是colour。 当您需要使用JavaScript(ES6和较新)破坏数组时,并且您只想拾取第二或第三个数组时,与使用 在这里,我们将数组作为具有其索引编号的对象的对象而破坏了数组,并给它一个别名 使用JavaScript,您可以使用数字分离器和指数符号使数字易于阅读。代码的执行保持完全相同,但它绝对容易阅读。 注意:数字分离器也可以使用其他语言来使用JavaScript以外的其他语言,例如Python,Kotlin,â 与我提到的有关编写一部分的重要性相似em>。 太多次了,我们看到以下代码,具有不必要的和毫无意义的 此代码很容易被更清晰的版本替换。 通过在上部变量中声明默认值,我们删除了 使用这种方法,我们尽早离开功能,以防止复杂且无法理解的嵌套条件。 承诺使您的代码更难阅读并倾向于增加代码cyclomatic complexity。 通过使用
我看到了用诸如许可证'和许可的词语的codebase > color - 或组织 组织 - 。
当您需要搜索术语 /重构一些代码,并且发现两个拼写时,它需要更多的时间并消耗更多的大脑空间,这可以通过遵循一致的拼写来避免。< / p>
破坏阵列元素 - 使其可读
,
跳过以前的数组键相比,有一种更干净的方法。
糟糕的方式
const meals = [
'Breakfast',
'Lunch',
'Apéro',
'Dinner'
];
const [, , , favoriteMeal] = meals;
console.log(favoriteMeal); // Dinner
推荐可读的方式
const meals = [
'Breakfast', // index 0
'Lunch', // index 1
'Apéro', // index 2
'Dinner' // index 3
];
const { 3: favoriteMeal } = meals; // Get the 4th value, index '3'
console.log(favoriteMeal); // Dinner
favoriteMeal
。
可读数字
没有数字分离器
const largeNumbers = 1000000000;
清晰/可读的数字
const largeNumbers = 1_000_000_000;
避免其他说法
else
块。
条件不必要的
else {}
const getUrl = () => {
if (options.includes('url')) {
return options.url;
} else {
return DEFAULT_URL;
}
}
选项1.使用默认值
const getUrl = () => {
let url = DEFAULT_URL;
if (options.includes('url')) {
url = options.url;
}
return url;
}
else {}
块的需求。
选项2.使用Guard Chauses方法
const getUrl = () => {
if (options.includes('url')) {
return options.url; // if true, we return `options.url` and leave the function
}
return DEFAULT_URL;
}
优先考虑
async/await
而不是承诺
有诺言
const isProfileNameAllowed = (id) => {
return profileModel.get(id).then((profile) => {
return Ban.name(profile.name);
}).then((ban) => ({
return ban.value
}).catch((err) => {
logger.error({ message: err.message });
});
}
使用
async
/await
const isProfileNameAllowed = async (id) => {
try {
const profile await profileModel.get(id);
const {value: result } = await Ban.name(profile.name);
return result;
} catch (err) {
logger.error({ message: err.message });
}
}
async
/await
,您避免回调地狱,当数据传递到通过一组功能时,这是由于其嵌套后的后备而导致无法控制的代码时发生的承诺。
没有魔术数字ð¢
尽可能多地避免使用可以随时间变化的硬码可变值,例如要显示的帖子总数,超时延迟和其他类似信息。
包含魔法数字的代码
setTimeout(() => {
window, (location.href = '/');
}, 3000);
getLatestBlogPost(0, 20);
没有硬编码数字
setTimeout(() => {
window, (location.href = '/');
}, config.REFRESH_DELAY_IN_MS);
const POSTS_PER_PAGE = 20;
getLatestBlogPost(0, POSTS_PER_PAGE);
始终使用assert.strictEqual
使用您的测试断言库(例如柴),请始终考虑使用严格的平等断言方法。
不只是使用assert.equal
assert.equal('+63464632781', phoneNumber);
assert.equal(validNumber, true);
•使用主张库中适当的严格功能
assert.strictEqual('+63464632781', phoneNumber);
assert.isTrue(validNumber);
更新对象 - 正确的方式
避免使用Object.assign
,因为它的冗长,更长的阅读
const user = Object.assign(data, {
name: 'foo',
email: 'foo@bar.co',
company: 'foo bar inc',
});
使用破坏性分配,传播语法
const user = {
...data,
name: 'foo',
email: 'foo@bar.co',
company: 'foo bar inc',
};
进行基准时停止使用Date()
JavaScript在您需要测量基准期间的页面性能时提供了更好的选择。
停止这样做
const start = new Date();
// your code ...
const end = new Date();
const executionTime = start.getTime() - end.getTime();
与performance.now()
一起
const start = performance.now();
// your code ...
const end = performade.now();
const executionTime = start - end;
锁定对象ð
创建对象时稳定锁定属性总是一个好主意。这样,您的属性对象的值只会仅读取。
不锁定对象
const canBeChanged = { name: 'Pierre' }:
canBeChanged.name = 'Henry'; // `name` is now "Henry"
使用as const
锁定对象
const cannotBeChanged = { name: 'Pierre' } as const;
cannotBeChanged = 'Henry'; // Won't be possible. JS will throw an error as `name` is now readonly
破坏物体时考虑别名
没有别名
const { data } = getUser(profileId);
const profileName = data.name;
// ...
用清晰的别名名称
const { data: profile } = getUser(profileId);
// then, use `profile` as the new var name 🙂
const profileName = profile.name;
// ...
始终使用严格的类型比较
进行某种比较时,请始终使用===
严格的比较。
不使用松散的比较
if ('abc' == true) {
} // this gives true ❌
if (props.address != details.address) {
} // result might not be what you expect
使用严格的比较
if ('abc' === true) {
} // This is false ✅
if (props.address !== details.address) {
} // Correct expectation
避免尽可能多地使用导出默认值
您应该避免使用export default
的主要原因是当您需要重命名类或组件名称时,重构非常复杂。
您必须更新导入的每个名称,因为它需要与默认导出类/函数/组件的实际名称匹配。
在进行大型项目时,除了花费更多的时间外,您还将增加忘记重命名进口(或简单地使用错别字)的机会。
分开导入每个功能/类将帮助您的IDE的智能启用和自动iMport在重构时正确拾取和自动IMPORT,而重命名的default export
不会如此。
一天结束时,与您的项目以及您选择哪种编码风味和惯例保持一致。
始终写纯粹的功能
如果一棵树落在树林中,它会发出声音吗?
如果纯函数会突变一些本地数据以产生不变的回报值,这可以吗?丰富的hickey。 Clojure的创建者
给定特定的输入(参数)到一个函数,纯函数始终返回相同的输出,因为纯函数不会修改其输入值。
纯函数永远不会产生副作用,这意味着它不会从其他功能中改变任何外部状态。纯函数仅取决于其输入参数以及函数的范围本身。有了他们,您只能将注意力集中在一个地方,这在阅读和调试代码时会产生巨大的不同。
function addition(x, y) {
return x + y;
}
当您传递对象时可能会发生更棘手的情况。
想象一下,您将用户对象传递给另一个功能。如果修改该函数中的对象,它将修改实际的用户对象,因为作为参数传递的对象实际上是对象的引用,这与独特的新克隆对象相反。
为了防止此不利之处,您将必须先粘结对象(您可以使用lodash clonedeep 函数),然后在返回时Object.freeze(copyUser)
。这将保证coperuser是不可变的。
例如:
import { cloneDeep as _cloneDeep } from 'lodash';
function changeUser(user) {
// copyUser = { …user };
const copyUser = _cloneDeep(user);
copyUser.name = 'Edward Ford';
return Object.freeze(copyUser);
}
通过编写纯函数,您将使代码易于阅读和理解。您只需要将注意力集中在功能本身上,而无需查看函数范围之外的周围环境,状态和属性,从而阻止您花费数小时调试。
在您的评论中使用TODO和FIXME前缀(真正需要评论时)
如果您必须稍后再进行更改,则可能需要在代码中发表评论,但是您必须使用TODO或FIXME前缀,以便在大多数IDE中强调您的代码。
最后,我还建议您vs code扩展TODO Tree,该TODO Tree列出了一个不错的待办事项清单。
示例ð
// TODO <JIRA-TICKET-ID> Change the logic to reflect to the release of productB
function somethingMeaningful() {}
衬里和格式化器
凹痕也很重要。具有一致的代码遵循您的产品的相同编码约定将有助于运输清洁和可读的代码。
为此作为git提交/推动代码时的预检查。最后,您可以很容易地为项目设置GitHub工作流动。
结论
编写清洁且可读的代码,该代码对明天的开发和维护至关重要。当我们为作业编写代码时,这不是我们的代码,而是每个人的代码。编写不需要大脑力量的代码的事实将阻止误解或通过使代码易于理解其在哪里讲述的误解或错误。
注意:该帖子来自我的原始编码指南,可在我的github https://github.com/pH-7/GoodJsCode
上提供