A mostly reasonable approach to JavaScript
Note: this guide assumes you are using Babel, and requires that you use babel-preset-airbnb or the equivalent. It also assumes you are installing shims/polyfills in your app, with airbnb-browser-shims or the equivalent.
This guide is available in other languages too. See Translation
Other Style Guides
<a name="types--primitives"></a><a name="1.1"></a>
1.1 Primitives: When you access a primitive type you work directly on its value.
stringnumberbooleannullundefinedsymbolbigintconst foo = 1; let bar = foo; bar = 9; console.log(foo, bar); // => 1, 9
<a name="types--complex"></a><a name="1.2"></a>
1.2 Complex: When you access a complex type you work on a reference to its value.
objectarrayfunctionconst foo = [1, 2]; const bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9
<a name="references--prefer-const"></a><a name="2.1"></a>
2.1 Use const for all of your references; avoid using var. eslint: prefer-const, no-const-assign
Why? This ensures that you can’t reassign your references, which can lead to bugs and difficult to comprehend code.
// bad var a = 1; var b = 2; // good const a = 1; const b = 2;
<a name="references--disallow-var"></a><a name="2.2"></a>
2.2 If you must reassign references, use let instead of var. eslint: no-var
Why?
letis block-scoped rather than function-scoped likevar.
// bad var count = 1; if (true) { count += 1; } // good, use the let. let count = 1; if (true) { count += 1; }
<a name="references--block-scope"></a><a name="2.3"></a>
2.3 Note that both let and const are block-scoped, whereas var is function-scoped.
// const and let only exist in the blocks they are defined in. { let a = 1; const b = 1; var c = 1; } console.log(a); // ReferenceError console.log(b); // ReferenceError console.log(c); // Prints 1
In the above code, you can see that referencing a and b will produce a ReferenceError, while c contains the number. This is because a and b are block scoped, while c is scoped to the containing function.
<a name="objects--no-new"></a><a name="3.1"></a>
3.1 Use the literal syntax for object creation. eslint: no-new-object
// bad const item = new Object(); // good const item = {};
<a name="es6-computed-properties"></a><a name="3.4"></a>
3.2 Use computed property names when creating objects with dynamic property names.
Why? They allow you to define all the properties of an object in one place.
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, };
<a name="es6-object-shorthand"></a><a name="3.5"></a>
3.3 Use object method shorthand. eslint: object-shorthand
// bad const atom = { value: 1, addValue: function (value) { return atom.value + value; }, }; // good const atom = { value: 1, addValue(value) { return atom.value + value; }, };
<a name="es6-object-concise"></a><a name="3.6"></a>
3.4 Use property value shorthand. eslint: object-shorthand
Why? It is shorter and descriptive.
const lukeSkywalker = 'Luke Skywalker'; // bad const obj = { lukeSkywalker: lukeSkywalker, }; // good const obj = { lukeSkywalker, };
<a name="objects--grouped-shorthand"></a><a name="3.7"></a>
3.5 Group your shorthand properties at the beginning of your object declaration.
Why? It’s easier to tell which properties are using the shorthand.
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, };
<a name="objects--quoted-props"></a><a name="3.8"></a>
3.6 Only quote properties that are invalid identifiers. eslint: quote-props
Why? In general we consider it subjectively easier to read. It improves syntax highlighting, and is also more easily optimized by many JS engines.
// bad const bad = { 'foo': 3, 'bar': 4, 'data-blah': 5, }; // good const good = { foo: 3, bar: 4, 'data-blah': 5, };
<a name="objects--prototype-builtins"></a>
3.7 Do not call Object.prototype methods directly, such as hasOwnProperty, propertyIsEnumerable, and isPrototypeOf. eslint: no-prototype-builtins
Why? These methods may be shadowed by properties on the object in question - consider
{ hasOwnProperty: false }- or, the object may be a null object (Object.create(null)). In modern browsers that support ES2022, or with a polyfill such as https://npmjs.com/object.hasown,Object.hasOwncan also be used as an alternative toObject.prototype.hasOwnProperty.call.
// 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
<a name="objects--rest-spread"></a>
3.8 Prefer the object spread syntax over Object.assign to shallow-copy objects. Use the object rest parameter syntax to get a new object with certain properties omitted. eslint: prefer-object-spread
// 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 }
<a name="arrays--literals"></a><a name="4.1"></a>
4.1 Use the literal syntax for array creation. eslint: no-array-constructor
// bad const items = new Array(); // good const items = [];
<a name="arrays--push"></a><a name="4.2"></a>
4.2 Use Array#push instead of direct assignment to add items to an array.
const someStack = []; // bad someStack[someStack.length] = 'abracadabra'; // good someStack.push('abracadabra');
<a name="es6-array-spreads"></a><a name="4.3"></a>
4.3 Use array spreads ... to copy arrays.
// bad const len = items.length; const itemsCopy = []; let i; for (i = 0; i < len; i += 1) { itemsCopy[i] = items[i]; } // good const itemsCopy = [...items];
<a name="arrays--from"></a> <a name="arrays--from-iterable"></a><a name="4.4"></a>
4.4 To convert an iterable object to an array, use spreads ... instead of Array.from
const foo = document.querySelectorAll('.foo'); // good const nodes = Array.from(foo); // best const nodes = [...foo];
<a name="arrays--from-array-like"></a>
4.5 Use Array.from for converting an array-like object to an array.
const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 }; // bad const arr = Array.prototype.slice.call(arrLike); // good const arr = Array.from(arrLike);
<a name="arrays--mapping"></a>
4.6 Use Array.from instead of spread ... for mapping over iterables, because it avoids creating an intermediate array.
// bad const baz = [...foo].map(bar); // good const baz = Array.from(foo, bar);
<a name="arrays--callback-return"></a><a name="4.5"></a>
4.7 Use return statements in array method callbacks. It’s ok to omit the return if the function body consists of a single statement returning an expression without side effects, following 8.2. eslint: array-callback-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


AI赋能电商视觉革命,一站式智能商拍平台
潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本,提升约3倍出图效率,让品牌能够快速上架。


企业专属的AI法律顾问
iTerms是法大大集团旗下法律子品牌,基于最先进的大语言模型(LLM)、专业的法律知识库和强大的智能体架构,帮助企业扫清合规障碍,筑牢风控防线,成为您企业专属的AI法律顾问。


稳定高效的流量提升解决方案,助力品牌曝光
稳定高效的流量提升解决方案,助力品牌曝光


最新版Sora2模型免费使用,一键生成无水印视频
最新版Sora2模型免费使用,一键生成无水印视频


实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。


选题、配图、成文,一站式创作,让内容运营更高效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。


AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。


最强AI数据分析助手
小浣熊家族Raccoon,您的AI智能助手,致力于通过先进的人工智能技术,为用户提供高效、便捷的智能服务。无论是日常咨询还是专业问题解答,小浣熊都能以快速、准确的响应满足您的需求,让您的生活更加智能便捷。


像人一样思考的AI智能体
imini 是一款超级AI智能体,能根据人类指令,自主思考、自主完成、并且交付结果的AI智能体。


AI数字人视频创作平台
Keevx 一款开箱即用的AI数字人视频创作平台,广泛适用于电商广告、企业培训与社媒宣传,让全球企业与个人创作者无需拍摄剪辑,就能快速生成多语言、高质量的专业视频。
最新AI工具、AI资讯
独家AI资源、AI项目落地

微信扫一扫关注公众号