尾随逗号,也被称为悬空逗号或终端逗号,是一个逗号符号,被打在一个元素列表的最后一项之后。自从引入 JavaScript语言 以来,尾随逗号在数组字面上是合法的。后来,对象字头也加入了数组。而随着ES2017(也称为ES8)的引入,尾随逗号几乎在所有地方都被允许。
这似乎是一个小变化,但有一些很难注意到的后果。虽然大多数新的语言特性都受到欢迎,但如果你不小心,这个特性会给你带来麻烦。
在本指南中,我们将详细介绍尾随逗号。我们将从常见的数据类型开始,比如数组和对象,在这些类型中,你可以安全地在项目列表的末尾添加尾部逗号。然后,我们将继续讨论语言结构,如参数列表、函数调用和结构化赋值。在文章的最后,我们将讨论使用尾随逗号的注意事项。
在数组中使用尾随逗号
你可以在数组中的最后一个表达式后面安全地加入一个尾随逗号,比如这样。
const arr = [
"one",
"two",
"three",
注意不要在最后加入一个以上的逗号,否则就会产生一个undefined
的元素。例如,下面这个数组是完全合法的,但包含四个元素。
const arr = [
"one",
"two",
"three",,
console.log(arr.length); // => 4
数组不一定有连续的索引,从0
。你可以创建一个包含若干 "空隙 "的数组--这样的数组被称为稀疏数组。例如,下面这个数组包含六个元素,其中三个是undefined
。
const sparseArray = [1,,,4,5,,];
所以,一定要记住,length
属性的值并不总是表示数组中元素的数量。你甚至可以有一个没有元素的数组,其长度为1
。
const arr = [,];
console.log(arr.length); // => 1
然而,在实践中,你很少需要处理一个稀疏的数组。如果你需要,你现有的代码很可能会像处理一个包含undefined
元素的正常数组一样来处理它。
在对象中使用尾部逗号
与数组类似,你可以在一个对象的最后一个属性后面加上逗号。
const person = {
firstName: "John",
lastName: "Davis",
age: 30,
从ECMAScript 5开始,对象字面的尾部逗号是合法的。一些JavaScript风格指南,比如Airbnb和Google创建的指南,甚至鼓励你养成一直使用尾部逗号的习惯,这样你以后在对象的末尾添加新属性时,就不容易遇到语法错误。
注意,与数组不同,你不能创建稀疏对象,试图这样做会导致语法错误。
const person = {
firstName: "John",
age: 30,
// logs:
// => Uncaught SyntaxError: Unexpected token ','
正如我之前提到的,除了数组和对象之外,JavaScript中还有几个结构体可以使用尾部逗号。
在参数列表和函数调用中使用尾随逗号
有时把函数的参数放在单独的一行是很有用的,特别是在有一个很长的参数列表或者你想容纳描述每个参数的注释的时候。比如说。
function createRectangle(
w, // (number) the width of the rectangle
h // (number) the height of the rectangle
) { /* ... */ }
随着函数的发展,你可能会发现自己处于一种需要向函数添加更多参数的情况。但每增加一个新的参数,你都要到前一行加一个逗号。
function createRectangularPrism(
w, // (number) the width
h, // (number) the height
d // (number) the depth
) { /* ... */ }
即使是有经验的开发者也不一定记得在前一行加逗号,这就导致了错误。更糟糕的是,提交的差异会显示那一行的代码变化,仅仅是因为你后来加了一个逗号(后面会详细介绍)。
幸运的是,ES2017让给函数参数添加尾部逗号也变得合法。
function createRectangularPrism(
w, // (number) the width
h, // (number) the height
d, // (number) the depth
) { /* ... */ }
这只是编码风格的改变,不会增加一个未命名的参数,也不会引起任何其他副作用。
更重要的是,ES2017的更新让我们能够在函数调用中的参数末尾有一个尾随的逗号。有些程序员喜欢把函数调用的每个参数放在自己的一行。如果你是他们中的一员,那么尾随逗号,同样会让你在未来避免潜在的错误。
createRectangle (
这段代码用两个参数调用createRectangle()
函数。如果你后来决定增加第三个参数,你就不必再编辑任何现有的行。这条规则同样适用于类或对象的方法定义,因为它们也是函数。
const myObj = {
createRectangle( // defines a method
) { /* ... */ }
在析构赋值语法中使用尾部逗号
解构赋值语法允许你从数组或对象中快速提取数值到不同的变量中。在进行析构时,你可以在赋值的左侧添加一个尾部逗号。例如,下面的代码是对一个数组进行析构。
const numbers = [10, 20, 30];
const [n1, n2, n3,] = numbers;
console.log(n1); // => 10
同样地,你可以使用解构法来 "解开 "一个对象的属性。
const car = {
color: 'red',
type: 'coupe',
hp: 500
const {color, type, hp,} = car;
console.log(color); // => red
但是JSON对象呢,它与普通的JavaScript对象类似?它们可以使用尾部逗号吗?
在JSON中使用尾随逗号
JSON文件格式是在21世纪初引入的。由于JSON是基于JavaScript的对象语法,而且它是在ECMAScript 5于2009年推出之前发明的,所以JSON中不能使用尾随逗号(记住,对象字面的尾随逗号在ES5中是合法的)。
例如,下面的代码会产生一个错误。
JSON.parse('[1, 2, 3, 4, ]');
// => Uncaught SyntaxError: Unexpected token ] in JSON at position 13
这一行代码也是如此。
JSON.parse('{"foo" : 1, }');
// => Uncaught SyntaxError: Unexpected token } in JSON at position 12
有许多在线工具可以帮助你解决这个问题。例如,你可以利用这个JSON格式化器来自动查找并删除JSON代码中的尾部逗号。
模块导入和导出中的尾部逗号
在现代JavaScript中,创建由独立代码块组成的程序是一种常见的做法,这些代码块被称为模块。就像在经典脚本中为对象添加尾部逗号是合法的一样,在模块中导出的最后一项之后添加逗号也是合法的。当你想在以后加入更多的出口时,这就很方便了。比如说。
// module 1
var foo = 10;
let bar = 20;
const baz = 30;
export {foo, bar, baz, };
这段代码使用export
关键字来使foo
,bar
, 和baz
变量公开。这意味着其他单独文件中的模块可以使用import
语句来访问这些变量。
// module 2
import {
baz, // notice the trailing comma, which is legal when importing identifiers
} from './module1.js'
为什么要开始使用尾部逗号?
JavaScript程序员曾经避免在数组中包含尾部逗号,因为早期版本的Internet Explorer会抛出一个错误(尽管它在JavaScript中从一开始就是合法的)。但是现在情况发生了变化。许多编码风格现在都建议一直使用尾部逗号,而且有很好的理由。
如果你经常在数组、对象或参数列表的末尾添加新的项目,那么如果已经有了尾随逗号,就意味着如果你以后需要添加新的项目,你就不必记得在前一行添加逗号。
你可能还会发现自己经常剪切和粘贴属性。同样,有一个尾部的逗号可以使重新排序的项目不那么麻烦,并防止将来发生语法错误。
此外,因为你不需要改变过去作为最后一项的那一行,版本控制系统会产生更干净的差异。假设你有这个函数。
function myFunction(
) { /* ... */ }
myFunction(
'arg1',
'arg2'
如果你添加了一个新的参数,叫做p3
,那么diff的输出就会是这样的。
function myFunction(
+ p2, // Change this line to add a comma
+ p3 // Add p3
) { /* ... */ }
myFunction (
'arg1',
- 'arg2'
+ 'arg2', // Change this line to add a comma
+ 'arg3' // Add arg3
这里,你在函数声明中有两个变化,在函数调用中有两个变化。让我们看看如果你的函数已经有了尾部逗号会发生什么。
function myFunction(
) { /* ... */ }
myFunction(
'arg1',
'arg2',
有了尾随逗号,你在diff输出中只有两个变化。
function myFunction(
+ p3 // Add p3
) { /* ... */ }
myFunction (
'arg1',
'arg2',
+ 'arg3' // Add arg3
本节的启示是,使用尾随逗号可以使你更容易为你的函数添加新的参数,或者复制/粘贴数组和对象中的属性。它也有助于产生更干净的差异输出。
但是,尾随逗号并不是在任何地方都有效,如果你不小心,使用它们可能会适得其反。
什么时候不使用尾随逗号
你可能认为你也可以在其他参数语法中使用尾随逗号,因为尾随逗号在其他各种JavaScript结构中是允许的。但实际上不是这样的。
function sum(...theArgs,) { // notice the trailing comma
return theArgs.reduce((previous, current) => {
return previous + current;
console.log(sum(1, 2, 3));
// => Uncaught SyntaxError: parameter after rest parameter
在休息参数后使用尾随逗号是非法的,即使你在结构化语法中使用它。
const numbers = [10, 20, 30];
const [n1, ...n2,] = numbers;
// => Uncaught SyntaxError: rest element may not have a trailing comma
所以,请记住,尽管在结构化语法中使用尾部逗号是有效的,但你不能在其余参数后使用它。
除了结构化语法,还有一个地方使用尾部逗号可能会给你带来麻烦:函数。考虑一下下面的例子。
function myFunction(,) { // ... } // => Uncaught SyntaxError: Unexpected token ','
myFunction(,); // => Uncaught SyntaxError: Unexpected token ','
这段代码的第一行定义了一个没有参数和逗号的函数,这导致SyntaxError
。你可以没有参数没有逗号,也可以在参数后有一个尾部逗号。当你调用一个函数时也是如此:你不能有一个函数调用的唯一参数是一个逗号。
在JavaScript语言中,逗号的使用经历了几次修订,随着每次修订,更多的语言结构都增加了对尾部逗号的支持。在这篇文章中,我们研究了尾随逗号在不同结构中的作用,包括数组、对象、JSON对象、参数列表、函数调用以及模块导入和导出。
然后,我们了解了在哪些地方使用尾音逗号是合法的,哪些地方不合法。一般来说,当你经常复制/粘贴属性或在列表末尾添加新项目时,你应该使用尾随逗号。你也可以利用它们来产生更干净的差异输出。但是,请记住,你不应该在其余参数语法中使用它们,而且你不能有一个函数声明/调用的唯一参数是逗号。
The postBest practices for using trailing commas in JavaScriptappeared first onLogRocket Blog.