{"id":13475528,"url":"https://github.com/bendc/frontend-guidelines","last_synced_at":"2025-10-08T22:43:18.552Z","repository":{"id":27640633,"uuid":"31125362","full_name":"bendc/frontend-guidelines","owner":"bendc","description":"Some HTML, CSS and JS best practices.","archived":false,"fork":false,"pushed_at":"2023-12-30T16:43:09.000Z","size":22,"stargazers_count":8361,"open_issues_count":5,"forks_count":659,"subscribers_count":326,"default_branch":"master","last_synced_at":"2025-10-08T22:43:17.423Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bendc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2015-02-21T12:46:17.000Z","updated_at":"2025-10-07T18:05:10.000Z","dependencies_parsed_at":"2024-01-21T04:43:31.676Z","dependency_job_id":null,"html_url":"https://github.com/bendc/frontend-guidelines","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bendc/frontend-guidelines","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bendc%2Ffrontend-guidelines","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bendc%2Ffrontend-guidelines/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bendc%2Ffrontend-guidelines/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bendc%2Ffrontend-guidelines/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bendc","download_url":"https://codeload.github.com/bendc/frontend-guidelines/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bendc%2Ffrontend-guidelines/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279000779,"owners_count":26082851,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-08T02:00:06.501Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T16:01:21.203Z","updated_at":"2025-10-08T22:43:18.532Z","avatar_url":"https://github.com/bendc.png","language":null,"readme":"# Frontend Guidelines\n\n## HTML\n\n### Semantics\n\nHTML5 provides us with lots of semantic elements aimed to describe precisely the content. Make sure you benefit from its rich vocabulary.\n\n```html\n\u003c!-- bad --\u003e\n\u003cdiv id=main\u003e\n  \u003cdiv class=article\u003e\n    \u003cdiv class=header\u003e\n      \u003ch1\u003eBlog post\u003c/h1\u003e\n      \u003cp\u003ePublished: \u003cspan\u003e21st Feb, 2015\u003c/span\u003e\u003c/p\u003e\n    \u003c/div\u003e\n    \u003cp\u003e…\u003c/p\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n\n\u003c!-- good --\u003e\n\u003cmain\u003e\n  \u003carticle\u003e\n    \u003cheader\u003e\n      \u003ch1\u003eBlog post\u003c/h1\u003e\n      \u003cp\u003ePublished: \u003ctime datetime=2015-02-21\u003e21st Feb, 2015\u003c/time\u003e\u003c/p\u003e\n    \u003c/header\u003e\n    \u003cp\u003e…\u003c/p\u003e\n  \u003c/article\u003e\n\u003c/main\u003e\n```\n\nMake sure you understand the semantics of the elements you're using. It's worse to use a semantic\nelement in a wrong way than staying neutral.\n\n```html\n\u003c!-- bad --\u003e\n\u003ch1\u003e\n  \u003cfigure\u003e\n    \u003cimg alt=Company src=logo.png\u003e\n  \u003c/figure\u003e\n\u003c/h1\u003e\n\n\u003c!-- good --\u003e\n\u003ch1\u003e\n  \u003cimg alt=Company src=logo.png\u003e\n\u003c/h1\u003e\n```\n\n### Brevity\n\nKeep your code terse. Forget about your old XHTML habits.\n\n```html\n\u003c!-- bad --\u003e\n\u003c!doctype html\u003e\n\u003chtml lang=en\u003e\n  \u003chead\u003e\n    \u003cmeta http-equiv=Content-Type content=\"text/html; charset=utf-8\" /\u003e\n    \u003ctitle\u003eContact\u003c/title\u003e\n    \u003clink rel=stylesheet href=style.css type=text/css /\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003ch1\u003eContact me\u003c/h1\u003e\n    \u003clabel\u003e\n      Email address:\n      \u003cinput type=email placeholder=you@email.com required=required /\u003e\n    \u003c/label\u003e\n    \u003cscript src=main.js type=text/javascript\u003e\u003c/script\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n\n\u003c!-- good --\u003e\n\u003c!doctype html\u003e\n\u003chtml lang=en\u003e\n  \u003cmeta charset=utf-8\u003e\n  \u003ctitle\u003eContact\u003c/title\u003e\n  \u003clink rel=stylesheet href=style.css\u003e\n\n  \u003ch1\u003eContact me\u003c/h1\u003e\n  \u003clabel\u003e\n    Email address:\n    \u003cinput type=email placeholder=you@email.com required\u003e\n  \u003c/label\u003e\n  \u003cscript src=main.js\u003e\u003c/script\u003e\n\u003c/html\u003e\n```\n\n### Accessibility\n\nAccessibility shouldn't be an afterthought. You don't have to be a WCAG expert to improve your\nwebsite, you can start immediately by fixing the little things that make a huge difference, such as:\n\n* learning to use the `alt` attribute properly\n* making sure your links and buttons are marked as such (no `\u003cdiv class=button\u003e` atrocities)\n* not relying exclusively on colors to communicate information\n* explicitly labelling form controls\n\n```html\n\u003c!-- bad --\u003e\n\u003ch1\u003e\u003cimg alt=Logo src=logo.png\u003e\u003c/h1\u003e\n\n\u003c!-- good --\u003e\n\u003ch1\u003e\u003cimg alt=Company src=logo.png\u003e\u003c/h1\u003e\n```\n\n### Language \u0026 character encoding\n\nWhile defining the language is optional, it's recommended to always declare\nit on the root element.\n\nThe HTML standard requires that pages use the UTF-8 character encoding.\nIt has to be declared, and although it can be declared in the Content-Type HTTP header,\nit is recommended to always declare it at the document level.\n\n```html\n\u003c!-- bad --\u003e\n\u003c!doctype html\u003e\n\u003ctitle\u003eHello, world.\u003c/title\u003e\n\n\u003c!-- good --\u003e\n\u003c!doctype html\u003e\n\u003chtml lang=en\u003e\n  \u003cmeta charset=utf-8\u003e\n  \u003ctitle\u003eHello, world.\u003c/title\u003e\n\u003c/html\u003e\n```\n\n### Performance\n\nUnless there's a valid reason for loading your scripts before your content, don't block the\nrendering of your page. If your style sheet is heavy, isolate the styles that are absolutely\nrequired initially and defer the loading of the secondary declarations in a separate style sheet.\nTwo HTTP requests is significantly slower than one, but the perception of speed is the most\nimportant factor.\n\n```html\n\u003c!-- bad --\u003e\n\u003c!doctype html\u003e\n\u003cmeta charset=utf-8\u003e\n\u003cscript src=analytics.js\u003e\u003c/script\u003e\n\u003ctitle\u003eHello, world.\u003c/title\u003e\n\u003cp\u003e...\u003c/p\u003e\n\n\u003c!-- good --\u003e\n\u003c!doctype html\u003e\n\u003cmeta charset=utf-8\u003e\n\u003ctitle\u003eHello, world.\u003c/title\u003e\n\u003cp\u003e...\u003c/p\u003e\n\u003cscript src=analytics.js\u003e\u003c/script\u003e\n```\n\n## CSS\n\n### Semicolons\n\nWhile the semicolon is technically a separator in CSS, always treat it as a terminator.\n\n```css\n/* bad */\ndiv {\n  color: red\n}\n\n/* good */\ndiv {\n  color: red;\n}\n```\n\n### Box model\n\nThe box model should ideally be the same for the entire document. A global\n`* { box-sizing: border-box; }` is fine, but don't change the default box model\non specific elements if you can avoid it.\n\n```css\n/* bad */\ndiv {\n  width: 100%;\n  padding: 10px;\n  box-sizing: border-box;\n}\n\n/* good */\ndiv {\n  padding: 10px;\n}\n```\n\n### Flow\n\nDon't change the default behavior of an element if you can avoid it. Keep elements in the\nnatural document flow as much as you can. For example, removing the white-space below an\nimage shouldn't make you change its default display:\n\n```css\n/* bad */\nimg {\n  display: block;\n}\n\n/* good */\nimg {\n  vertical-align: middle;\n}\n```\n\nSimilarly, don't take an element off the flow if you can avoid it.\n\n```css\n/* bad */\ndiv {\n  width: 100px;\n  position: absolute;\n  right: 0;\n}\n\n/* good */\ndiv {\n  width: 100px;\n  margin-left: auto;\n}\n```\n\n### Positioning\n\nThere are many ways to position elements in CSS. Favor modern layout specifications\nsuch as Flexbox and Grid, and avoid removing elements from the normal document flow, for example\nwith `position: absolute`.\n\n### Selectors\n\nMinimize selectors tightly coupled to the DOM. Consider adding a class to the elements\nyou want to match when your selector exceeds 3 structural pseudo-classes, descendant or\nsibling combinators.\n\n```css\n/* bad */\ndiv:first-of-type :last-child \u003e p ~ *\n\n/* good */\ndiv:first-of-type .info\n```\n\nAvoid overloading your selectors when you don't need to.\n\n```css\n/* bad */\nimg[src$=svg], ul \u003e li:first-child {\n  opacity: 0;\n}\n\n/* good */\n[src$=svg], ul \u003e :first-child {\n  opacity: 0;\n}\n```\n\n### Specificity\n\nDon't make values and selectors hard to override. Minimize the use of `id`'s\nand avoid `!important`.\n\n```css\n/* bad */\n.bar {\n  color: green !important;\n}\n.foo {\n  color: red;\n}\n\n/* good */\n.foo.bar {\n  color: green;\n}\n.foo {\n  color: red;\n}\n```\n\n### Overriding\n\nOverriding styles makes selectors and debugging harder. Avoid it when possible.\n\n```css\n/* bad */\nli {\n  visibility: hidden;\n}\nli:first-child {\n  visibility: visible;\n}\n\n/* good */\nli + li {\n  visibility: hidden;\n}\n```\n\n### Inheritance\n\nDon't duplicate style declarations that can be inherited.\n\n```css\n/* bad */\ndiv h1, div p {\n  text-shadow: 0 1px 0 #fff;\n}\n\n/* good */\ndiv {\n  text-shadow: 0 1px 0 #fff;\n}\n```\n\n### Brevity\n\nKeep your code terse. Use shorthand properties and avoid using multiple properties when\nit's not needed.\n\n```css\n/* bad */\ndiv {\n  transition: all 1s;\n  top: 50%;\n  margin-top: -10px;\n  padding-top: 5px;\n  padding-right: 10px;\n  padding-bottom: 20px;\n  padding-left: 10px;\n}\n\n/* good */\ndiv {\n  transition: 1s;\n  top: calc(50% - 10px);\n  padding: 5px 10px 20px;\n}\n```\n\n### Language\n\nPrefer English over math.\n\n```css\n/* bad */\n:nth-child(2n + 1) {\n  transform: rotate(360deg);\n}\n\n/* good */\n:nth-child(odd) {\n  transform: rotate(1turn);\n}\n```\n\n### Vendor prefixes\n\nKill obsolete vendor prefixes aggressively. If you need to use them, insert them before the\nstandard property.\n\n```css\n/* bad */\ndiv {\n  transform: scale(2);\n  -webkit-transform: scale(2);\n  -moz-transform: scale(2);\n  -ms-transform: scale(2);\n  transition: 1s;\n  -webkit-transition: 1s;\n  -moz-transition: 1s;\n  -ms-transition: 1s;\n}\n\n/* good */\ndiv {\n  -webkit-transform: scale(2);\n  transform: scale(2);\n  transition: 1s;\n}\n```\n\n### Animations\n\nFavor transitions over animations. Avoid animating other properties than\n`opacity` and `transform`.\n\n```css\n/* bad */\ndiv:hover {\n  animation: move 1s forwards;\n}\n@keyframes move {\n  100% {\n    margin-left: 100px;\n  }\n}\n\n/* good */\ndiv:hover {\n  transition: 1s;\n  transform: translateX(100px);\n}\n```\n\n### Units\n\nUse unitless values when you can. Favor `rem` if you use relative units. Prefer seconds over\nmilliseconds.\n\n```css\n/* bad */\ndiv {\n  margin: 0px;\n  font-size: .9em;\n  line-height: 22px;\n  transition: 500ms;\n}\n\n/* good */\ndiv {\n  margin: 0;\n  font-size: .9rem;\n  line-height: 1.5;\n  transition: .5s;\n}\n```\n\n### Colors\n\nIf you need transparency, use `rgba`. Otherwise, always use the hexadecimal format.\n\n```css\n/* bad */\ndiv {\n  color: hsl(103, 54%, 43%);\n}\n\n/* good */\ndiv {\n  color: #5a3;\n}\n```\n\n### Drawing\n\nAvoid HTTP requests when the resources are easily replicable with CSS.\n\n```css\n/* bad */\ndiv::before {\n  content: url(white-circle.svg);\n}\n\n/* good */\ndiv::before {\n  content: \"\";\n  display: block;\n  width: 20px;\n  height: 20px;\n  border-radius: 50%;\n  background: #fff;\n}\n```\n\n### Hacks\n\nDon't use them.\n\n```css\n/* bad */\ndiv {\n  // position: relative;\n  transform: translateZ(0);\n}\n\n/* good */\ndiv {\n  /* position: relative; */\n  will-change: transform;\n}\n```\n\n## JavaScript\n\n### Performance\n\nFavor readability, correctness and expressiveness over performance. JavaScript will basically never\nbe your performance bottleneck. Optimize things like image compression, network access and DOM\nreflows instead. If you remember just one guideline from this document, choose this one.\n\n```javascript\n// bad (albeit way faster)\nconst arr = [1, 2, 3, 4];\nconst len = arr.length;\nvar i = -1;\nvar result = [];\nwhile (++i \u003c len) {\n  var n = arr[i];\n  if (n % 2 \u003e 0) continue;\n  result.push(n * n);\n}\n\n// good\nconst arr = [1, 2, 3, 4];\nconst isEven = n =\u003e n % 2 == 0;\nconst square = n =\u003e n * n;\n\nconst result = arr.filter(isEven).map(square);\n```\n\n### Statelessness\n\nTry to keep your functions pure. All functions should ideally produce no side-effects, use no outside data and return new objects instead of mutating existing ones.\n\n```javascript\n// bad\nconst merge = (target, ...sources) =\u003e Object.assign(target, ...sources);\nmerge({ foo: \"foo\" }, { bar: \"bar\" }); // =\u003e { foo: \"foo\", bar: \"bar\" }\n\n// good\nconst merge = (...sources) =\u003e Object.assign({}, ...sources);\nmerge({ foo: \"foo\" }, { bar: \"bar\" }); // =\u003e { foo: \"foo\", bar: \"bar\" }\n```\n\n### Natives\n\nRely on native methods as much as possible.\n\n```javascript\n// bad\nconst toArray = obj =\u003e [].slice.call(obj);\n\n// good\nconst toArray = (() =\u003e\n  Array.from ? Array.from : obj =\u003e [].slice.call(obj)\n)();\n```\n\n### Coercion\n\nEmbrace implicit coercion when it makes sense. Avoid it otherwise. Don't cargo-cult.\n\n```javascript\n// bad\nif (x === undefined || x === null) { ... }\n\n// good\nif (x == undefined) { ... }\n```\n\n### Loops\n\nDon't use loops as they force you to use mutable objects. Rely on `array.prototype` methods.\n\n```javascript\n// bad\nconst sum = arr =\u003e {\n  var sum = 0;\n  var i = -1;\n  for (;arr[++i];) {\n    sum += arr[i];\n  }\n  return sum;\n};\n\nsum([1, 2, 3]); // =\u003e 6\n\n// good\nconst sum = arr =\u003e\n  arr.reduce((x, y) =\u003e x + y);\n\nsum([1, 2, 3]); // =\u003e 6\n```\nIf you can't, or if using `array.prototype` methods is arguably abusive, use recursion.\n\n```javascript\n// bad\nconst createDivs = howMany =\u003e {\n  while (howMany--) {\n    document.body.insertAdjacentHTML(\"beforeend\", \"\u003cdiv\u003e\u003c/div\u003e\");\n  }\n};\ncreateDivs(5);\n\n// bad\nconst createDivs = howMany =\u003e\n  [...Array(howMany)].forEach(() =\u003e\n    document.body.insertAdjacentHTML(\"beforeend\", \"\u003cdiv\u003e\u003c/div\u003e\")\n  );\ncreateDivs(5);\n\n// good\nconst createDivs = howMany =\u003e {\n  if (!howMany) return;\n  document.body.insertAdjacentHTML(\"beforeend\", \"\u003cdiv\u003e\u003c/div\u003e\");\n  return createDivs(howMany - 1);\n};\ncreateDivs(5);\n```\n\nHere's a [generic loop function](https://gist.github.com/bendc/6cb2db4a44ec30208e86) making recursion easier to use.\n\n### Arguments\n\nForget about the `arguments` object. The rest parameter is always a better option because:\n\n1. it's named, so it gives you a better idea of the arguments the function is expecting\n2. it's a real array, which makes it easier to use.\n\n```javascript\n// bad\nconst sortNumbers = () =\u003e\n  Array.prototype.slice.call(arguments).sort();\n\n// good\nconst sortNumbers = (...numbers) =\u003e numbers.sort();\n```\n\n### Apply\n\nForget about `apply()`. Use the spread operator instead.\n\n```javascript\nconst greet = (first, last) =\u003e `Hi ${first} ${last}`;\nconst person = [\"John\", \"Doe\"];\n\n// bad\ngreet.apply(null, person);\n\n// good\ngreet(...person);\n```\n\n### Bind\n\nDon't `bind()` when there's a more idiomatic approach.\n\n```javascript\n// bad\n[\"foo\", \"bar\"].forEach(func.bind(this));\n\n// good\n[\"foo\", \"bar\"].forEach(func, this);\n```\n```javascript\n// bad\nconst person = {\n  first: \"John\",\n  last: \"Doe\",\n  greet() {\n    const full = function() {\n      return `${this.first} ${this.last}`;\n    }.bind(this);\n    return `Hello ${full()}`;\n  }\n}\n\n// good\nconst person = {\n  first: \"John\",\n  last: \"Doe\",\n  greet() {\n    const full = () =\u003e `${this.first} ${this.last}`;\n    return `Hello ${full()}`;\n  }\n}\n```\n\n### Higher-order functions\n\nAvoid nesting functions when you don't have to.\n\n```javascript\n// bad\n[1, 2, 3].map(num =\u003e String(num));\n\n// good\n[1, 2, 3].map(String);\n```\n\n### Composition\n\nAvoid multiple nested function calls. Use composition instead.\n\n```javascript\nconst plus1 = a =\u003e a + 1;\nconst mult2 = a =\u003e a * 2;\n\n// bad\nmult2(plus1(5)); // =\u003e 12\n\n// good\nconst pipeline = (...funcs) =\u003e val =\u003e funcs.reduce((a, b) =\u003e b(a), val);\nconst addThenMult = pipeline(plus1, mult2);\naddThenMult(5); // =\u003e 12\n```\n\n### Caching\n\nCache feature tests, large data structures and any expensive operation.\n\n```javascript\n// bad\nconst contains = (arr, value) =\u003e\n  Array.prototype.includes\n    ? arr.includes(value)\n    : arr.some(el =\u003e el === value);\ncontains([\"foo\", \"bar\"], \"baz\"); // =\u003e false\n\n// good\nconst contains = (() =\u003e\n  Array.prototype.includes\n    ? (arr, value) =\u003e arr.includes(value)\n    : (arr, value) =\u003e arr.some(el =\u003e el === value)\n)();\ncontains([\"foo\", \"bar\"], \"baz\"); // =\u003e false\n```\n\n### Variables\n\nFavor `const` over `let` and `let` over `var`.\n\n```javascript\n// bad\nvar me = new Map();\nme.set(\"name\", \"Ben\").set(\"country\", \"Belgium\");\n\n// good\nconst me = new Map();\nme.set(\"name\", \"Ben\").set(\"country\", \"Belgium\");\n```\n\n### Conditions\n\nFavor IIFE's and return statements over if, else if, else and switch statements.\n\n```javascript\n// bad\nvar grade;\nif (result \u003c 50)\n  grade = \"bad\";\nelse if (result \u003c 90)\n  grade = \"good\";\nelse\n  grade = \"excellent\";\n\n// good\nconst grade = (() =\u003e {\n  if (result \u003c 50)\n    return \"bad\";\n  if (result \u003c 90)\n    return \"good\";\n  return \"excellent\";\n})();\n```\n\n### Object iteration\n\nAvoid `for...in` when you can.\n\n```javascript\nconst shared = { foo: \"foo\" };\nconst obj = Object.create(shared, {\n  bar: {\n    value: \"bar\",\n    enumerable: true\n  }\n});\n\n// bad\nfor (var prop in obj) {\n  if (obj.hasOwnProperty(prop))\n    console.log(prop);\n}\n\n// good\nObject.keys(obj).forEach(prop =\u003e console.log(prop));\n```\n\n### Objects as Maps\n\nWhile objects have legitimate use cases, maps are usually a better, more powerful choice. When in\ndoubt, use a `Map`.\n\n```javascript\n// bad\nconst me = {\n  name: \"Ben\",\n  age: 30\n};\nvar meSize = Object.keys(me).length;\nmeSize; // =\u003e 2\nme.country = \"Belgium\";\nmeSize++;\nmeSize; // =\u003e 3\n\n// good\nconst me = new Map();\nme.set(\"name\", \"Ben\");\nme.set(\"age\", 30);\nme.size; // =\u003e 2\nme.set(\"country\", \"Belgium\");\nme.size; // =\u003e 3\n```\n\n### Curry\n\nCurrying is a powerful but foreign paradigm for many developers. Don't abuse it as its appropriate\nuse cases are fairly unusual.\n\n```javascript\n// bad\nconst sum = a =\u003e b =\u003e a + b;\nsum(5)(3); // =\u003e 8\n\n// good\nconst sum = (a, b) =\u003e a + b;\nsum(5, 3); // =\u003e 8\n```\n\n### Readability\n\nDon't obfuscate the intent of your code by using seemingly smart tricks.\n\n```javascript\n// bad\nfoo || doSomething();\n\n// good\nif (!foo) doSomething();\n```\n```javascript\n// bad\nvoid function() { /* IIFE */ }();\n\n// good\n(function() { /* IIFE */ }());\n```\n```javascript\n// bad\nconst n = ~~3.14;\n\n// good\nconst n = Math.floor(3.14);\n```\n\n### Code reuse\n\nDon't be afraid of creating lots of small, highly composable and reusable functions.\n\n```javascript\n// bad\narr[arr.length - 1];\n\n// good\nconst first = arr =\u003e arr[0];\nconst last = arr =\u003e first(arr.slice(-1));\nlast(arr);\n```\n```javascript\n// bad\nconst product = (a, b) =\u003e a * b;\nconst triple = n =\u003e n * 3;\n\n// good\nconst product = (a, b) =\u003e a * b;\nconst triple = product.bind(null, 3);\n```\n\n### Dependencies\n\nMinimize dependencies. Third-party is code you don't know. Don't load an entire library for just a couple of methods easily replicable:\n\n```javascript\n// bad\nvar _ = require(\"underscore\");\n_.compact([\"foo\", 0]));\n_.unique([\"foo\", \"foo\"]);\n_.union([\"foo\"], [\"bar\"], [\"foo\"]);\n\n// good\nconst compact = arr =\u003e arr.filter(el =\u003e el);\nconst unique = arr =\u003e [...new Set(arr)];\nconst union = (...arr) =\u003e unique([].concat(...arr));\n\ncompact([\"foo\", 0]);\nunique([\"foo\", \"foo\"]);\nunion([\"foo\"], [\"bar\"], [\"foo\"]);\n```\n","funding_links":[],"categories":["Others","Software Engineering Best Practices","Platforms","Generic","Best Practice ##","3. 浏览器扩展(Chrome Extensions) ##","Styleguides","6. 在线工具"],"sub_categories":["Frontend","Frontend Development","Version 1.x ###","13.20 视差滚动(Parallax Scrolling) ###","Other","24.3 Web Sockets"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbendc%2Ffrontend-guidelines","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbendc%2Ffrontend-guidelines","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbendc%2Ffrontend-guidelines/lists"}