ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

前端代码规范

2026/8/8 19:41:28 拓冰建站 浏览量
前端代码规范

GitHub - airbnb/javascript: JavaScript Style Guide

变量

1.避免使用var

为什么?这确保您无法重新分配引用,这可能会导致错误和难以理解的代码。

// bad
var a = 1;
var b = 2;// good
const a = 1;
const b = 2;

2. 如果必须分配引用,则使用let代替var

let是块级作用域

// bad
var count = 1;
if (true) {count += 1;
}// good, use the let.
let count = 1;
if (true) {count += 1;
}

let都是const块作用域,而var是函数作用域。

{let a = 1;const b = 1;var c = 1;
}
console.log(a); // Error
console.log(b); // Error
console.log(c); // 1

对象

1.使用文字语法创建对象

// bad
const item = new Object();// good
const item = {};

2.创建具有动态属性名称的对象时,使用计算属性名称。  

它们允许您在一处定义对象的所有属性。

function getKey(k) {return `a key named ${k}`;
}// bad
const obj = {id: 5,name: 'San Francisco',
};
obj[getKey('enabled')] = true;// good
const obj = {id: 5,name: 'San Francisco',[getKey('enabled')]: true,
};

3.使用对象方法简写  

// bad
const atom = {value: 1,addValue: function (value) {return atom.value + value;},
};// good
const atom = {value: 1,addValue(value) {return atom.value + value;},
};

 4.使用属性值简写

它更短且具有描述性。 

const lukeSkywalker = 'Luke Skywalker';// bad
const obj = {lukeSkywalker: lukeSkywalker,
};// good
const obj = {lukeSkywalker,
};

5.在对象声明的开头对简写属性进行分组。  

使用简写更容易辨别哪些属性。

const anakinSkywalker = 'Anakin Skywalker';
const lukeSkywalker = 'Luke Skywalker';// bad
const obj = {episodeOne: 1,twoJediWalkIntoACantina: 2,lukeSkywalker,episodeThree: 3,mayTheFourth: 4,anakinSkywalker,
};// good
const obj = {lukeSkywalker,anakinSkywalker,episodeOne: 1,twoJediWalkIntoACantina: 2,episodeThree: 3,mayTheFourth: 4,
};

6.仅引用无效标识符的属性。 

一般来说,我们主观上认为它更容易阅读。它改进了语法高亮,并且也更容易被许多 JS 引擎优化。 

// bad
const bad = {'foo': 3,'bar': 4,'data-blah': 5,
};// good
const good = {foo: 3,bar: 4,'data-blah': 5,
};

 7.不要直接使用Object.prototype

不要Object.prototype直接调用 hasOwnPropertypropertyIsEnumerable、isPrototypeOf等方法。 

// bad
console.log(object.hasOwnProperty(key));// good
console.log(Object.prototype.hasOwnProperty.call(object, key));// better
const has = Object.prototype.hasOwnProperty; // cache the lookup once, in module scope.
console.log(has.call(object, key));// best
console.log(Object.hasOwn(object, key)); // only supported in browsers that support ES2022/* or */
import has from 'has'; // https://www.npmjs.com/package/has
console.log(has(object, key));
/* or */
console.log(Object.hasOwn(object, key)); // https://www.npmjs.com/package/object.hasown

8.优先使用对象扩展语法 

优先使用对象扩展语法而不是Object.assign浅复制对象。使用对象剩余参数语法来获取省略某些属性的新对象。 

// very bad
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 }); // this mutates `original` ಠ_ಠ
delete copy.a; // so does this// bad
const original = { a: 1, b: 2 };
const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }// good
const original = { a: 1, b: 2 };
const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }const { a, ...noA } = copy; // noA => { b: 2, c: 3 }

 数组

1.使用文字语法创建数组

// bad
const items = new Array();// good
const items = [];

2.使用Array#push而不是直接赋值来将项目添加到数组中。

const someStack = [];// bad
someStack[someStack.length] = 'abracadabra';// good
someStack.push('abracadabra');

3.使用数组扩展...来复制数组。

// bad
const len = items.length;
const itemsCopy = [];
let i;for (i = 0; i < len; i += 1) {itemsCopy[i] = items[i];
}// good
const itemsCopy = [...items];

4.要将可迭代对象转换为数组,请使用 Spread...而不是Array.from 

const foo = document.querySelectorAll('.foo');// good
const nodes = Array.from(foo);// best
const nodes = [...foo];

5.用于Array.from将类似数组的对象转换为数组。 

const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };// bad
const arr = Array.prototype.slice.call(arrLike);// good
const arr = Array.from(arrLike);

6.使用Array.from而不是扩展...来映射可迭代对象,因为它避免了创建中间数组。

// bad
const baz = [...foo].map(bar);// good
const baz = Array.from(foo, bar);

7.在数组方法回调中使用 return 语句。如果函数体由返回一个没有副作用的表达式的单个语句组成,则可以省略 return。

// good
[1, 2, 3].map((x) => {const y = x + 1;return x * y;
});// good
[1, 2, 3].map((x) => x + 1);// bad - no returned value means `acc` becomes undefined after the first iteration
[[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => {const flatten = acc.concat(item);
});// good
[[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => {const flatten = acc.concat(item);return flatten;
});// bad
inbox.filter((msg) => {const { subject, author } = msg;if (subject === 'Mockingbird') {return author === 'Harper Lee';} else {return false;}
});// good
inbox.filter((msg) => {const { subject, author } = msg;if (subject === 'Mockingbird') {return author === 'Harper Lee';}return false;
});

8.如果数组有多行,则在左数组括号之后和右数组括号之前使用换行符 

// bad
const arr = [[0, 1], [2, 3], [4, 5],
];const objectInArray = [{id: 1,
}, {id: 2,
}];const numberInArray = [1, 2,
];// good
const arr = [[0, 1], [2, 3], [4, 5]];const objectInArray = [{id: 1,},{id: 2,},
];const numberInArray = [1,2,
];

解构

1.访问和使用对象的多个属性时使用对象解构。

为什么?解构使您无需为这些属性创建临时引用,也无需重复访问该对象。重复对象访问会产生更多重复代码,需要更多阅读,并产生更多出错机会。解构对象还提供了块中使用的对象结构的单一定义,而不需要读取整个块来确定使用的内容。

// bad
function getFullName(user) {const firstName = user.firstName;const lastName = user.lastName;return `${firstName} ${lastName}`;
}// good
function getFullName(user) {const { firstName, lastName } = user;return `${firstName} ${lastName}`;
}// best
function getFullName({ firstName, lastName }) {return `${firstName} ${lastName}`;
}

2.使用数组解构

const arr = [1, 2, 3, 4];// bad
const first = arr[0];
const second = arr[1];// good
const [first, second] = arr;

3.对多个返回值使用对象解构,而不是数组解构。

您可以随着时间的推移添加新属性或更改事物的顺序,而不会破坏调用站点。 

// bad
function processInput(input) {// then a miracle occursreturn [left, right, top, bottom];
}// the caller needs to think about the order of return data
const [left, __, top] = processInput(input);// good
function processInput(input) {// then a miracle occursreturn { left, right, top, bottom };
}// the caller selects only the data they need
const { left, top } = processInput(input);

 模块

1.始终在非标准模块系统上使用模块 ( import/export )

模块是未来,让我们现在就开始使用未来。

// bad
const AirbnbStyleGuide = require('./AirbnbStyleGuide');
module.exports = AirbnbStyleGuide.es6;// ok
import AirbnbStyleGuide from './AirbnbStyleGuide';
export default AirbnbStyleGuide.es6;// best
import { es6 } from './AirbnbStyleGuide';
export default es6;

2.不要使用通配符导入

这可确保您有一个默认导出

// bad
import * as AirbnbStyleGuide from './AirbnbStyleGuide';// good
import AirbnbStyleGuide from './AirbnbStyleGuide';

3.不要直接导入导出。 

尽管一行语句很简洁,但采用一种清晰的导入方式和一种清晰的导出方式可以使事情保持一致。

// bad
// filename es6.js
export { es6 as default } from './AirbnbStyleGuide';// good
// filename es6.js
import { es6 } from './AirbnbStyleGuide';
export default es6;

4.只从一个地方的路径导入

从同一路径导入多行会使代码更难维护。

// bad
import foo from 'foo';
// … some other imports … //
import { named1, named2 } from 'foo';// good
import foo, { named1, named2 } from 'foo';// good
import foo, {named1,named2,
} from 'foo';

5.不要导出可变绑定

一般来说,应该避免突变,尤其是在导出可变绑定时。虽然某些特殊情况可能需要此技术,但一般来说,只应导出常量引用。 

// bad
let foo = 3;
export { foo };// good
const foo = 3;
export { foo };

6.在具有单个导出的模块中,优先选择默认导出而不是命名导出

鼓励更多只导出一项内容的文件,这更有利于可读性和可维护性 

// bad
export function foo() {}// good
export default function foo() {}

7.将以上所有内容放入import非导入声明中

由于import 是提升的,因此将它们全部放在顶部可以防止出现意外的行为。 

// bad
import foo from 'foo';
foo.init();import bar from 'bar';// good
import foo from 'foo';
import bar from 'bar';foo.init();

8. 多行导入应该像多行数组和对象文字一样缩进

大括号遵循与样式指南中所有其他大括号块相同的缩进规则,尾随逗号也是如此。

// bad
import {longNameA, longNameB, longNameC, longNameD, longNameE} from 'path';// good
import {longNameA,longNameB,longNameC,longNameD,longNameE,
} from 'path';

9.模块导入语句中不允许使用 Webpack 加载器语法

由于在导入中使用 Webpack 语法会将代码耦合到模块捆绑器

// bad
import fooSass from 'css!sass!foo.scss';
import barCss from 'style!css!bar.css';// good
import fooSass from 'foo.scss';
import barCss from 'bar.css';

 10.不要包含 JavaScript 文件扩展名

包含扩展会抑制重构,并且会对您在每个使用者中导入的模块的实现细节进行不适当的硬编码。

// bad
import foo from './foo.js';
import bar from './bar.jsx';
import baz from './baz/index.jsx';// good
import foo from './foo';
import bar from './bar';
import baz from './baz';