整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

JavaScript代码风格参考指南

码必须尽可能的清晰和易读。

这实际上是一种编程艺术 —— 以一种正确并且人们易读的方式编码来完成一个复杂的任务。一个良好的代码风格大大有助于实现这一点。

一、语法

下面是一个备忘单,其中列出了一些建议的规则(详情请参阅下文):

现在,让我们详细讨论一下这些规则和它们的原因吧。

没有什么规则是“必须”的

没有什么规则是“刻在石头上”的。这些是风格偏好,而不是宗教教条。

二、花括号

在大多数的 JavaScript 项目中,花括号以 “Egyptian” 风格(译注:“egyptian” 风格又称 K&R 风格 — 代码段的开括号位于一行的末尾,而不是另起一行的风格)书写,左花括号与相应的关键词在同一行上 — 而不是新起一行。左括号前还应该有一个空格,如下所示:

if (condition) {
  // do this
  // ...and that
  // ...and that
}

单行构造(如 if (condition) doSomething())也是一个重要的用例。我们是否应该使用花括号?如果是,那么在哪里?

下面是这几种情况的注释,你可以自己判断一下它们的可读性:

  1. 初学者常这样写。非常不好!这里不需要花括号:if (n < 0) {alert(`Power ${n} is not supported`);}
  2. 拆分为单独的行,不带花括号。永远不要这样做,添加新行很容易出错:if (n < 0) alert(`Power ${n} is not supported`);
  3. 写成一行,不带花括号 — 如果短的话,也是可以的:if (n < 0) alert(`Power ${n} is not supported`);
  4. 最好的方式:if (n < 0) { alert(`Power ${n} is not supported`); }

对于很短的代码,写成一行是可以接受的:例如 if (cond) return null。但是代码块(最后一个示例)通常更具可读性。

三、行的长度

没有人喜欢读一长串代码,最好将代码分割一下。

例如:

// 回勾引号 ` 允许将字符串拆分为多行
let str = `
  ECMA International's TC39 is a group of JavaScript developers,
  implementers, academics, and more, collaborating with the community
  to maintain and evolve the definition of JavaScript.
`;

对于 if 语句:

if (
  id === 123 &&
  moonPhase === 'Waning Gibbous' &&
  zodiacSign === 'Libra'
) {
  letTheSorceryBegin();
}

一行代码的最大长度应该在团队层面上达成一致。通常是 80 或 120 个字符。

四、缩进

有两种类型的缩进:

  • 水平方向上的缩进:2 或 4 个空格。一个水平缩进通常由 2 或 4 个空格或者 “Tab” 制表符(key Tab)构成。选择哪一个方式是一场古老的圣战。如今空格更普遍一点。选择空格而不是 tabs 的优点之一是,这允许你做出比 “Tab” 制表符更加灵活的缩进配置。例如,我们可以将参数与左括号对齐,像下面这样:
show(parameters,
     aligned, // 5 spaces padding at the left
     one,
     after,
     another
  ) {
  // ...
}
  • 垂直方向上的缩进:用于将代码拆分成逻辑块的空行。即使是单个函数通常也被分割为数个逻辑块。在下面的示例中,初始化的变量、主循环结构和返回值都被垂直分割了:
function pow(x, n) {
  let result = 1;
  //              <--
  for (let i = 0; i < n; i++) {
    result *= x;
  }
  //              <--
  return result;
}


插入一个额外的空行有助于使代码更具可读性。写代码时,不应该出现连续超过 9 行都没有被垂直分割的代码。

五、分号

每一个语句后面都应该有一个分号。即使它可以被跳过。

有一些编程语言的分号确实是可选的,那些语言中也很少使用分号。但是在 JavaScript 中,极少数情况下,换行符有时不会被解释为分号,这时代码就容易出错。更多内容请参阅 代码结构 一章的内容。

如果你是一个有经验的 JavaScript 程序员,你可以选择像 StandardJS 这样的无分号的代码风格。否则,最好使用分号以避免可能出现的陷阱。大多数开发人员都应该使用分号。

六、嵌套的层级

尽量避免代码嵌套层级过深。

例如,在循环中,有时候使用 continue 指令以避免额外的嵌套是一个好主意。

例如,不应该像下面这样添加嵌套的 if 条件:

for (let i = 0; i < 10; i++) {
  if (cond) {
    ... // <- 又一层嵌套
  }
}

我们可以这样写:

for (let i = 0; i < 10; i++) {
  if (!cond) continue;
  ...  // <- 没有额外的嵌套
} //多用这种风格。

使用 if/elsereturn 也可以做类似的事情。

例如,下面的两个结构是相同的。

第一个:

function pow(x, n) {
  if (n < 0) {
    alert("Negative 'n' not supported");
  } else {
    let result = 1;

    for (let i = 0; i < n; i++) {
      result *= x;
    }

    return result;
  }
}

第二个:

function pow(x, n) {
  if (n < 0) {
    alert("Negative 'n' not supported");
    return;
  }

  let result = 1;

  for (let i = 0; i < n; i++) {
    result *= x;
  }

  return result;
}

但是第二个更具可读性,因为 n < 0 这个“特殊情况”在一开始就被处理了。一旦条件通过检查,代码执行就可以进入到“主”代码流,而不需要额外的嵌套。

七、函数位置

如果你正在写几个“辅助”函数和一些使用它们的代码,那么有三种方式来组织这些函数。

  1. 在调用这些函数的代码的 上方 声明这些函数:
// function declarations
function createElement() {
  ...
}

function setHandler(elem) {
  ...
}

function walkAround() {
  ...
}

// the code which uses them
let elem = createElement();
setHandler(elem);
walkAround();
  1. 先写调用代码,再写函数
// the code which uses the functions
let elem = createElement();
setHandler(elem);
walkAround();

// --- helper functions ---
function createElement() {
  ...
}

function setHandler(elem) {
  ...
}

function walkAround() {
  ...
}
  1. 混合:在第一次使用一个函数时,对该函数进行声明。

大多数情况下,第二种方式更好。

这是因为阅读代码时,我们首先想要知道的是“它做了什么”。如果代码先行,那么在整个程序的最开始就展示出了这些信息。之后,可能我们就不需要阅读这些函数了,尤其是它们的名字清晰地展示出了它们的功能的时候。

八、风格指南

风格指南包含了“如果编写”代码的通用规则,例如:使用哪个引号、用多少空格来缩进、一行代码最大长度等非常多的细节。

当团队中的所有成员都使用相同的风格指南时,代码看起来将是统一的。无论是团队中谁写的,都是一样的风格。

当然,一个团队可以制定他们自己的风格指南,但是没必要这样做。现在已经有了很多制定好的代码风格指南可供选择。

一些受欢迎的选择:

  • Google JavaScript 风格指南
  • Airbnb JavaScript 风格指南
  • Idiomatic.JS
  • StandardJS
  • 还有很多……

如果你是一个初学者,你可以从本章中上面的内容开始。然后你可以浏览其他风格指南,并选择一个你最喜欢的。

九、自动检查器

检查器(Linters)是可以自动检查代码样式,并提出改进建议的工具。

它们的妙处在于进行代码风格检查时,还可以发现一些代码错误,例如变量或函数名中的错别字。因此,即使你不想坚持某一种特定的代码风格,我也建议你安装一个检查器。

下面是一些最出名的代码检查工具:

  • JSLint — 第一批检查器之一。
  • JSHint — 比 JSLint 多了更多设置。
  • ESLint — 应该是最新的一个。

它们都能够做好代码检查。我使用的是 ESLint。

大多数检查器都可以与编辑器集成在一起:只需在编辑器中启用插件并配置代码风格即可。

例如,要使用 ESLint 你应该这样做:

  1. 安装 Node.JS。
  2. 使用 npm install -g eslint 命令(npm 是一个 JavaScript 包安装工具)安装 ESLint。
  3. 在你的 JavaScript 项目的根目录(包含该项目的所有文件的那个文件夹)创建一个名为 .eslintrc 的配置文件。
  4. 在集成了 ESLint 的编辑器中安装/启用插件。大多数编辑器都有这个选项。

下面是一个 .eslintrc 文件的例子:

{
  "extends": "eslint:recommended",
  "env": {
    "browser": true,
    "node": true,
    "es6": true
  },
  "rules": {
    "no-console": 0,
    "indent": 2
  }
}

这里的 "extends" 指令表示我们是基于 “eslint:recommended” 的设置项而进行设置的。之后,我们制定我们自己的规则。

你也可以从网上下载风格规则集并进行扩展。有关安装的更多详细信息

此外,某些 IDE 有内置的检查器,这非常方便,但是不像 ESLint 那样可自定义。

十、总结

本文描述的(和提到的代码风格指南中的)所有语法规则,都旨在帮助你提高代码可读性。它们都是值得商榷的。

当我们思考如何写“更好”的代码的时候,我们应该问自己的问题是:“什么可以让代码可读性更高,更容易被理解?”和“什么可以帮助我们避免错误?”这些是我们讨论和选择代码风格时要牢记的主要原则。

阅读流行的代码风格指南,可以帮助你了解有关代码风格的变化趋势和最佳实践的最新想法。

为手机备忘录,好多人再熟悉不过,有些人用它随手札记,有些人用它记录秘密,有些人认为根本用不上。可是,这个小小的备忘录,你真的了解吗?你知道它隐藏的那些秘密功能吗?

1、 速记功能:有个想法,说出来

想随时随地记录您的重要事项或灵光一闪的金点子,只需说出来。

在华为手机主界面,屏幕解锁状态下,从屏幕边缘的速记区域向内滑动。即可打开备忘录"速记"功能,可以通过语音、文字或照片方式迅速创建笔记或者创建待办。并且,备忘录会将语音转换为文字,并同时记录语音和文字。

速记gif

设置方法:打开备忘录,选择左上角图标"☰"> 设置 > 速记,打开速记开关。在提示界面打开在其他应用上层显示,并设置入口位置为屏幕左侧或屏幕右侧。

二、待办管理:它提醒您,误不了

情人节那天,因为备忘录的提醒,我没有忘记买礼物。

重要事项,却总担心忘了,可以让备忘录帮你记住。备忘录支持语音录入待办事项,提醒方式有指定时间和指定位置。

*指定位置:当经过设置的目的地有效范围并超过1分钟时,闹钟会提醒。

操作方法:全部待办列表界面输入待办事项后,点击

添加提醒,设置指定时间/智能位置

三、手写涂鸦:画出来,更生动

文字表达不清楚,寥寥几笔的绘画可能更生动形象,备忘录也可以变身画板。

除了速记助手,手写涂鸦也让人相见恨晚。打开备忘录并进入编辑笔记模式。除了语音、文字和图片三种方式,还可进行涂鸦。无论是文档注释还是绘画创意,都可以肆意书写。

操作方法:选择笔记 >

,点击

,手写您要记录的内容。

四、速记分享:一键分享,简单

想把备忘录里的内容发个朋友圈,可以轻松一键分享。

速记的内容保存为笔记后,可以一键分享到微博、微信,精彩内容传递更便捷。

操作方法:全部笔记全部待办列表界面,打开要分享的备忘录,点击

,按屏幕提示完成分享。

五、更贴心:误删了,没关系

1.最近删除:挽回误删事项

一不小心删掉的笔记和待办事项,没关系!可以在"最近删除"中找到并恢复。多一重保障,多一份安心。

2..多端同步:备忘内容不丢失

支持多设备数据同步,通过华为账号,随时随地查看和编辑你的备忘录信息。

HUAWEI P30 系列手机上,有AI注入的备忘录,就像拥有灵魂一般,它所能做的与过去相比,已经不可同日而语,让我们感受一下这小小的身躯里那些大大的能量吧。

*不同机型对上述功能的支持情况各有差异,请以手机实际为准。

发现更多精彩功能请下滑主屏幕,搜索"玩机技巧"应用

HUAWEI P30 系列新品开售,点击以下图片立即拥有!

移动端跳转链接:

PC端跳转链接:https://www.vmall.com/product/10086501288078.html?cid=90002

里有一些我最喜欢的关于编写更简洁的 Javascript 代码的技巧。

1.忘掉var

使用constlet声明所有变量。根据经验,默认情况下使用const,否则如果需要重新分配变量,则使用let

应避免使用var关键字,因为它几乎不受作用域限制导致潜在的作用域错误,请参阅我的提升指南。

好处:最佳实践是在创建变量时初始化变量,这样您和您的团队就可以确保没有变量被闲置。

// ❌ Avoid this
var old = "";

// ✅ Do this
const immutable = "John";
let counter = 1;
counter++; // counter === 2;

// Declare objects and arrays as const to prevent type change
const user = {firstname: "John", lastname: "Doe"};
const users = ["Mac", "Roe"];

2、使用严格相等(===)

严格相等运算符(===)与相等运算符相同,检查两个操作数是否相等,并返回布尔结果。但与相等运算符 ( == )不同,严格相等运算符(===)始终认为不同类型的操作数是不同的。

好处:在非严格相等运算符的情况下,0 为假将错误地等于假。

// ❌ Avoid this
1 == "1"; // true
0 == false; // true

// ✅ Do this
1 === 1; // true
1 === "1"; // false
0 === false; // false

3. 避免使用原始对象的构造函数

原始对象与其原始对象完全不同,这使得它们在包装在对象中时更难以检查严格相等性。

它们基本上是等价的,但不相等。

// ❌ Avoid this
const stringObject = new String("Charly");

// ✅ Do this
const stringPrimitive = "Charly";

// Equality check
stringPrimitive === stringObject; // false 
new Number(1) === 1; // false
new Boolean(true) === true; // false

4. 使用对象文字

对象字面量是一种速记符号,允许您动态定义对象或数组。

从而避免重复,提高可读性并防止错误,因为我们无法推断其背后的逻辑,我们当前是在初始化变量还是更新它?

// ❌ Avoid this
const user = new Object(); // {}
user.firstname = "John"; // { firstname: "John" }
user.lastname = "Doe"; // { firstname: "John", lastname: "Doe" }

// ✅ Do this
const user = { 
  firstname: "John", 
  lastname: "Doe" 
};

// ❌ Avoid this
const fruits = new Array(); // []
fruits.push("banana"); // ["banana"]
fruits.push("mango"); // ["banana", "mango"]

// ✅ Do this
const fruits = ["banana", "mango"];

5. 使用模板文字来组合字符串

将字符串放在一起是一件痛苦的事情,尤其是在组合字符串和变量时。

为了使这个过程更简单,您可以使用模板文字(用反引号标记),它同时接受字符串变量,只要它被插值(${})包围即可。

const firstname = "John";

// ❌ Avoid this
let greeting = "Hello, " + firstname; // Hello, John

// ✅ Do this
greeting = `Hello, ${firstname}`; // Hello, John

6. 使用分号作为行终止符

使用分号作为行终止始终是一个好习惯。

如果您忘记了它,则不会收到警告,因为在大多数情况下它将由 JavaScript 解析器插入。但如果没有它,你怎么知道表达式何时结束呢?

以for循环为例:

// ✅ Do this
for (let i = 0; i < numbers.length; i++) {
  console.log(numbers[i]);
}

您将无法执行以下操作,因为解析器认为它是一个表达式,而实际上它是三个独立的表达式:

// ❌ Not this
for (let i = 0 i < numbers.length i++) {
  console.log(numbers[i]);
} // Uncaught SyntaxError: Unexpected identifier

7. 使用对象参数代替多个参数

我认为在函数中定义太多参数是一种f坏代码味道。即使参数有默认值或者是可选的,我们还是以这个例子为例:

// ❌ Avoid this
function avatarUrl(avatar, format = "small", caption = true) {
  // Does something
}

avatarUrl(user.avatar, 'thumb', false)

当您使用此函数时,很难知道使用了哪些参数以及如何使用。最后一个参数false在这里代表什么?

不知道,我们必须打开函数定义才能知道。
如果您需要更改参数的顺序会发生什么?那么您必须更改所有函数调用。

对于对象来说,顺序并不重要:

// ✅ Do this
function avatarUrl(avatar, options={format: 'small', caption: true}) {
  // Does something
}

avatarUrl(user.avatar, {
  format: "thumb", 
  caption: false
})

8.尽早返回

嵌套条件使代码难以理解,但您可以通过提前返回来使用保护子句轻松避免它。

保护子句将允许您删除大部分 else 条件,使您的代码像简单的英语一样可读。

// ❌ Avoid this
function doSomething() {
  if (user) {
    if (user.role === "ADMIN") {
      return 'Administrator';
    } else {
      return 'User';
    }
  } else {
    return 'Anonymous';
  }
}

// ✅ Do this
function doSomething() {
  if (!user) return 'Anonymous'
  if (user.role === "ADMIN") return 'Administrator'

  return 'User'
}

9.学习并使用内置函数的力量

Javascript 在ArrayObjectString上提供了很多内置函数。

找到并学习它们,以充分发挥堆栈的威力。

// ❌ Avoid this
const users = [
  {
    username: "JohnDoe",
    admin: false
  },
  {
    username: "Todd",
    admin: true
  },
];
const admins = [];

function getAdmins() {
  users.forEach((user) => {
    if (user.admin) admins.push(user)
  })

  return admins
}

// ✅ Do this
function getAdmins() {
  return users.filter((user) => user.admin)
}

10. 代码是为人类编写的,而不是为计算机编写的

让我们假设,我们大多数人都不善于注意到差异,我们可能需要几秒钟才能注意到逻辑上的 not (!)。

让我们看这个例子:

const users = [
  {
    username: "JohnDoe",
    admin: false
    enabled: true
  },
  {
    username: "Todd",
    admin: true
    enabled: true
  },
];

// ❌ Avoid this
const members = users.filter(u => u.enabled).map(u => !u.admin)
const admins = users.filter(u => u.enabled).map(u => u.admin)

// ✅ Do this
const enabledUsers = users.filter(u => u.enabled)
const members = enabledUsers.map(u => !u.admin)
const admins = enabledUsers.map(u => u.admin)

成员和管理员分配的区别仅在于逻辑非 (!),如果您需要更改一项分配,那么您还需要更改另一项分配。

另一个例子,不要使用幻数。使用显式变量代替:

// ❌ Avoid this
function price_with_taxes(price) {
  return price * 1.2
}

// ✅ Do this
const taxRate = 1.2
function price_with_taxes(price) {
  return price * taxRate
}

11.避免缩写

无论您将“e”写为“event”,还是将“t”写为“ticket”,都不会提高您的工作效率,但会降低可读性并降低即时理解能力。

// ❌ Avoid this
function someFunction() {
  events.forEach(e => {
    e.tickets.forEach(t => {
      `${e.name} for ${t.full_name}`
    })
  })
}

// ✅ Do this
function someFunction() {
  events.forEach(event => {
    event.tickets.forEach(ticket => {
      `${event.name} for ${ticket.full_name}`
    })
  })
}

在这里你不必猜测 e 和 t 代表什么,你只需阅读即可。
编码非常复杂,额外的复杂性足以让您感到臃肿。这也适用于变量、类、方法......

但也有少数例外,在 for 循环中使用广泛使用的缩写(如 i)是可以的。

12.避免无用的&&否定条件

条件就像大脑的备忘录,因为您需要在逐步执行每一行代码时记住它们,以便了解发生了什么。

幸运的是,由于我最喜欢的 ES6 操作符可选链接,其中大多数都可以得到简化。

// ❌ Avoid this
function doSomething(params) {
  if (params && params.filter) return 'Foo'

  return 'Bar'
}

// ✅ Do this
function doSomething(params) {
  if (params?.filter) return 'Foo'

  return 'Bar'
}

我不了解你,但每次我看到逻辑不(!)时,我的大脑都会暂停一秒钟,对我来说,读到这样的内容感觉更自然:

如果用户是管理员那么我们就这样做

而不是:

如果用户不是管理员,那么我们就会这样做。

// ❌ Avoid this
function doSomething(user) {
  if (!user || !user.admin) {
    // Case where no user or not admin
  } else {
    // Case where user and user is admin
  }
}

// ✅ Do this
function doSomething(user) {
  if (user && user.admin) {
    // Case where user and user is admin
  } else {
    // Case where no user or not admin
  }
}

13.使用for...of代替for循环

使用for...of语句代替经典的for 循环就是 JavaScript 的一项改进。

这个语法是 ES6 引入的,它包含一个内置的迭代器,这样你就不必定义自己的变量,将其递增直到某个长度值:

let users = ["Fedor Emelianenko", "Cyril Gane", "Conor McGregor"];

// ❌ Avoid this
// This avoids length behind reavaluated at every iteration
let usersCount = users.length;
for (let i = 0; i < usersCount; i++) {
    console.log(users[i]);
}

// ✅ Do this
for(let user of users) {
    console.log(users);
}

请注意它的可读性有多强!而且您不必关心所有这些 (let i = 0; i < usersCount; i++) 笨拙的逻辑,尽管您可能需要它用于某些特定的用例,例如不规则的间隔。

14. 可读的代码胜过聪明的代码

永远记住,您正在与其他开发人员以及未来的自己一起编写代码。您不想制造比编写代码要解决的问题更多的问题。

不要编写代码来炫耀你的技能,编写每个人都可以理解和调试的代码。

如果您有更多提示,我很乐意在评论中向您学习!

把事情简单化!