来源: 互联网
发布时间: 2022-05-17
次浏览
1.对相同类型的变量使用相同的词汇
Bad:
getUserInfo();
getClientData();
getCustomerRecord();
Good:
getUser();
2.使用可搜索的名称
Bad:
// What the heck is 86400000 for?
setTimeout(blastOff, 86400000);
Good:
// Declare them as capitalized named constants.
const MILLISECONDS_PER_DAY = 60 * 60 * 24 * 1000; //86400000;
setTimeout(blastOff, MILLISECONDS_PER_DAY);
3.不要添加不需要的上下文
如果您的类/对象名称告诉您某些信息,请不要在变量名称中重复。
Bad:
const Car = {
carMake: "Honda",
carModel: "Accord",
carColor: "Blue"
};
function paintCar(car, color) {
car.carColor = color;
}
Good:
const Car = {
make: "Honda",
model: "Accord",
color: "Blue"
};
function paintCar(car, color) {
car.color = color;
}
4.函数参数(理想情况下为 2 个或更少)
5.函数应该做一件事
这是迄今为止软件工程中最重要的规则。当函数做不止一件事时,它们就更难组合、测试和推理。当您可以将一个函数隔离为一个操作时,
它可以很容易地重构,并且您的代码会读起来更清晰。如果您从本指南中除此之外没有任何其他内容,那么您将领先于许多开发人员。
Bad:
function emailClients(clients) {
clients.forEach(client => {
const clientRecord = database.lookup(client);
if (clientRecord.isActive()) {
email(client);
}
});
}
Good:
function emailActiveClients(clients) {
clients.filter(isActiveClient).forEach(email);
}
function isActiveClient(client) {
const clientRecord = database.lookup(client);
return clientRecord.isActive();
}
6.函数名称应该说明它们的作用
Bad:
function addToDate(date, month) {
// ...
}
const date = new Date();
// It's hard to tell from the function name what is added
addToDate(date, 1);
Good:
function addMonthToDate(month, date) {
// ...
}
const date = new Date();
addMonthToDate(1, date);
6.函数应该只是一个抽象级别
当您有多个抽象级别时,您的函数通常做得太多。拆分功能导致可重用性和更容易的测试。
7.删除重复代码
尽最大努力避免重复代码。重复代码是不好的,因为这意味着如果您需要更改某些逻辑,则可以在多个地方进行更改。
想象一下,如果您经营一家餐馆并跟踪您的库存:所有的西红柿、洋葱、大蒜、香料等。如果您有多个清单要保留,
那么当您提供带有西红柿的菜肴时,所有清单都必须更新在他们中。如果您只有一个列表,那么只有一个地方可以更新!
通常你有重复的代码,因为你有两个或多个稍微不同的东西,它们有很多共同点,但它们的差异迫使你有两个或多个独立的函数来做很多相同的事情。
删除重复代码意味着创建一个抽象,它可以只用一个函数/模块/类来处理这组不同的事情。
获得正确的抽象是至关重要的,这就是为什么你应该遵循类部分中列出的 SOLID 原则。糟糕的抽象可能比重复代码更糟糕,所以要小心!
说了这么多,如果你能做出好的抽象,那就去做吧!不要重复自己,否则你会发现自己在想要更改一件事时更新多个地方。
8.使用 Object.assign 设置默认对象
9.不要使用标志作为函数参数
标志告诉你的用户,这个函数做不止一件事。函数应该做一件事。如果它们基于布尔值遵循不同的代码路径,则拆分您的函数。
Bad:
function createFile(name, temp) {
if (temp) {
fs.create(`./temp/${name}`);
} else {
fs.create(name);
}
}
Good:
function createFile(name) {
fs.create(name);
}
function createTempFile(name) {
createFile(`./temp/${name}`);
}
10.不要写入全局函数
污染全局变量在 JavaScript 中是一种不好的做法,因为您可能会与另一个库发生冲突,并且您的 API 的用户将一无所知,直到他们在生产中遇到异常。
让我们考虑一个例子:如果您想扩展 JavaScript 的原生 Array 方法以拥有一个diff可以显示两个数组之间差异的方法怎么办?
您可以将新函数写入 . Array.prototype,但它可能会与尝试执行相同操作的另一个库发生冲突。
如果其他库只是diff用来查找数组的第一个元素和最后一个元素之间的差异怎么办?
这就是为什么只使用 ES2015/ES6 类并简单地扩展全局会更好的原因Array。
Bad:
Array.prototype.diff = function diff(comparisonArray) {
const hash = new Set(comparisonArray);
return this.filter(elem => !hash.has(elem));
};
Good:
class SuperArray extends Array {
diff(comparisonArray) {
const hash = new Set(comparisonArray);
return this.filter(elem => !hash.has(elem));
}
}
11.封装条件
Bad:
if (fsm.state === "fetching" && isEmpty(listNode)) {
// ...
}
Good:
function shouldShowSpinner(fsm, listNode) {
return fsm.state === "fetching" && isEmpty(listNode);
}
if (shouldShowSpinner(fsmInstance, listNodeInstance)) {
// ...
}
12.避免否定条件
Bad:
function isDOMNodeNotPresent(node) {
// ...
}
if (!isDOMNodeNotPresent(node)) {
// ...
}
Good:
function isDOMNodePresent(node) {
// ...
}
if (isDOMNodePresent(node)) {
// ...
}
13.避免条件
这似乎是一项不可能完成的任务。第一次听到这个,大多数人都会说,“我怎么能在没有if声明的情况下做任何事情呢?”
答案是在许多情况下,您可以使用多态性来完成相同的任务。第二个问题通常是,“这很好,但我为什么要这样做?”
答案是我们之前学到的一个干净的代码概念:一个函数应该只做一件事。当你的类和函数有if语句时,
你是在告诉你的用户你的函数做不止一件事。记住,只做一件事。
Bad:
class Airplane {
// ...
getCruisingAltitude() {
switch (this.type) {
case "777":
return this.getMaxAltitude() - this.getPassengerCount();
case "Air Force One":
return this.getMaxAltitude();
case "Cessna":
return this.getMaxAltitude() - this.getFuelExpenditure();
}
}
}
Good:
class Airplane {
// ...
}
class Boeing777 extends Airplane {
// ...
getCruisingAltitude() {
return this.getMaxAltitude() - this.getPassengerCount();
}
}
class AirForceOne extends Airplane {
// ...
getCruisingAltitude() {
return this.getMaxAltitude();
}
}
class Cessna extends Airplane {
// ...
getCruisingAltitude() {
return this.getMaxAltitude() - this.getFuelExpenditure();
}
}
14.删除死代码
死代码与重复代码一样糟糕。没有理由将其保留在您的代码库中。如果它没有被调用,请摆脱它!
如果您仍然需要它,它在您的版本历史记录中仍然是安全的。
15.使用方法链
这种模式在 JavaScript 中非常有用,您可以在 jQuery 和 Lodash 等许多库中看到它。它使您的代码具有表现力,并且不那么冗长。
出于这个原因,我说,使用方法链并看看你的代码有多干净。
在您的类函数中,只需this在每个函数的末尾返回,您就可以将更多的类方法链接到它上面。
Bad:
class Car {
constructor(make, model, color) {
this.make = make;
this.model = model;
this.color = color;
}
setMake(make) {
this.make = make;
}
setModel(model) {
this.model = model;
}
setColor(color) {
this.color = color;
}
save() {
console.log(this.make, this.model, this.color);
}
}
const car = new Car("Ford", "F-150", "red");
car.setColor("pink");
car.save();
Good:
class Car {
constructor(make, model, color) {
this.make = make;
this.model = model;
this.color = color;
}
setMake(make) {
this.make = make;
// NOTE: Returning this for chaining
return this;
}
setModel(model) {
this.model = model;
// NOTE: Returning this for chaining
return this;
}
setColor(color) {
this.color = color;
// NOTE: Returning this for chaining
return this;
}
save() {
console.log(this.make, this.model, this.color);
// NOTE: Returning this for chaining
return this;
}
}
const car = new Car("Ford", "F-150", "red").setColor("pink").save();
16.Async/Await 比 Promises 更干净
Promise 是回调的一个非常干净的替代方案,但是 ES2017/ES8 带来了 async 和 await,它提供了一个更干净的解决方案。
您所需要的只是一个以async关键字为前缀的函数,然后您可以在没有then函数链的情况下强制编写逻辑。
如果您现在可以利用 ES2017/ES8 功能,请使用它!
Bad:
import { get } from "request-promise";
import { writeFile } from "fs-extra";
get("https://en.wikipedia.org/wiki/Robert_Cecil_Martin")
.then(body => {
return writeFile("article.html", body);
})
.then(() => {
console.log("File written");
})
.catch(err => {
console.error(err);
});
Good:
import { get } from "request-promise";
import { writeFile } from "fs-extra";
async function getCleanCodeArticle() {
try {
const body = await get(
"https://en.wikipedia.org/wiki/Robert_Cecil_Martin"
);
await writeFile("article.html", body);
console.log("File written");
} catch (err) {
console.error(err);
}
}
getCleanCodeArticle()
17.函数调用者和被调用者应该关闭
如果一个函数调用另一个函数,请将这些函数垂直靠近源文件。理想情况下,将调用者保持在被调用者的正上方。
我们倾向于从上到下阅读代码,就像报纸一样。因此,请让您的代码以这种方式阅读。
18.只对复杂不太好理解的代码注释
19.不要在代码库中留下已经注释掉的代码