{"id":23655223,"url":"https://github.com/caplin/styleguide","last_synced_at":"2025-11-22T07:30:15.474Z","repository":{"id":9773202,"uuid":"11744230","full_name":"caplin/StyleGuide","owner":"caplin","description":"A javascript style guide","archived":false,"fork":false,"pushed_at":"2015-03-26T10:37:30.000Z","size":344,"stargazers_count":2,"open_issues_count":2,"forks_count":3,"subscribers_count":5,"default_branch":"gh-pages","last_synced_at":"2024-12-28T19:52:03.391Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://caplin.github.io/StyleGuide","language":"CSS","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/caplin.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}},"created_at":"2013-07-29T16:30:31.000Z","updated_at":"2017-08-24T15:45:37.000Z","dependencies_parsed_at":"2022-07-31T14:09:39.310Z","dependency_job_id":null,"html_url":"https://github.com/caplin/StyleGuide","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caplin%2FStyleGuide","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caplin%2FStyleGuide/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caplin%2FStyleGuide/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/caplin%2FStyleGuide/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/caplin","download_url":"https://codeload.github.com/caplin/StyleGuide/tar.gz/refs/heads/gh-pages","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239627287,"owners_count":19670844,"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","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-12-28T19:51:57.528Z","updated_at":"2025-11-22T07:30:15.397Z","avatar_url":"https://github.com/caplin.png","language":"CSS","funding_links":[],"categories":[],"sub_categories":[],"readme":"---\nlayout: main\npermalink: /index.html\ntitle: Caplin Style Guide for Javascript\n---\n\n\n\nCaplin Style Guide for JavaScript\n=================================\n\nA javascript style guide drawing heavily from other style guides (in particular [Felix's Node Style Guide](http://nodeguide.com/style.html), and somewhat inspired by [idiomatic.js](https://github.com/rwldrn/idiomatic.js/)) but favouring explicitness and minimisation of potential for error over terseness.\n\nAs with any style guide, some of these rules are debateable. Having a consistent style throughout the codebase is more valuable than getting any specific rule 'right'.\n\n\u003e Break any of these rules sooner than say anything outright barbarous.\n\u003e\n\u003e *Politics and the English Language*, George Orwell\n\nThis guide is written in markdown.  The readable version is [here](http://caplin.github.io/StyleGuide/), and the source is [here](https://github.com/caplin/StyleGuide).\n\n\nReligion\n--------\nTabs not spaces. So it is written, so let it be done.\n\nConfiguring your editor to show whitespace characters will help you be consistent.  I have their opacity set to 30/255 so that they don't interfere visually.\n\n\nSemicolons\n----------\nSemicolons after **every** statement except:\n\n- Control flow ending with curly brackets (if/while/etc).\n- Function Declarations - Function Expressions DO require a trailing semicolon!\n\nFailing to understand JavaScript's ASI (automatic semicolon insertion) can cause bugs (*note that when code is concatenated, you don't always have control over what is above you*):\n\n```javascript\n// Working Function Declaration\n// ASI happens after parsing the token \"}\"\n// The same behaviour exists for the flow control statements, therefore semicolon is not necessary\n// (but example() should be on a new line!)\nfunction example() {\n    console.log('test');\n} example();\n\n// Not working Function Declaration: Throws Syntax Error\n// ASI does not happen after \")\"\n(function example() {\n    console.log('test')\n}()) example();\n\n// Working Function Expression\nvar example = function() {}; example();\n\n// Not working Function Expression: Throws Syntax Error\nvar example = function() {} example();\n```\n\nBraces\n------\nOpening braces go on the same line as the statement:\n\n*Right:*\n\n```javascript\nif (true) {\n\tconsole.log('winning');\n}\n```\n\n*Wrong:*\n\n```javascript\nif (true)\n{\n\tconsole.log('losing');\n}\n```\n\nCode blocks must always be surrounded in braces, even if they are only a single line.\n\n*Wrong:*\n\n```javascript\nif (true) console.log('losing');\n```\n\nQuotes\n------\nUse single quotes instead of double quotes. You can use double quotes if the string will itself contain single quotes, so you can avoid escaping them.\nReasons for single quotes: less effort to type them and they have less visual clutter.\n\n\nObject / Array\n--------------\nDon't use the Array constructor to create an array containing particular values. Use the literal form for that.\n\n```javascript\nvar x = new Array('this', 'is', 'wrong');\nvar y = ['this', 'is', 'right'];\n```\nThis is because the Array constructor treats its arguments inconsistently.  A single numeric argument defines the size of the array, while any other kind of argument list provides initial values.  Avoid confusion by always using the literal notation to provide initial array values.\n\nShort declarations can be on a single line, otherwise start a new line for each item.  When split over multiple lines, commas go at the end of the line not the beginning.\n\n*Right:*\n\n```javascript\nvar myArray = [\n\t'first',\n\t'second',\n\t'third'\n];\n```\n\n*Wrong:*\n\n```javascript\nvar myArray = [\n\t'first'\n\t, 'second'\n\t, 'third'\n];\n```\n\nDon't leave trailing commas.\n\nOnly quote keys in Object literals when required.\n\n\nConditionals\n------------\nIt's easy to assume that the behaviour of `if (x)` is the same as `if (x == true)`.  This is **NOT TRUE**.  There are numerous differences.  In fact, the behaviour is the same as `if (Boolean(x))`, a relationship often referred to as 'truthiness'.\n\nThe truthiness rules are not well known by all developers, and relying on them without being sure of exactly which types may be in the relevant variables leads to bugs.  Worse, the errors can be difficult to track down and when you look at code that depends on truthiness, it is not possible to know if the developer who wrote that code knew exactly what they were doing or not.\n\nIt is better to be explicit in what you check.\n\n*OK:*\n\n```javascript\nif (bob !== null) {\n\t// This is explicit.\n\tconsole.log('this code is executed if bob is not null.');\n}\n```\n\n*Wrong:*\n\n```javascript\nif (bob) {\n\t// This relies on truthiness.\n\tconsole.log('Executed if bob is not null, undefined, 0, false, NaN or the empty string.').\n}\n```\n\nWrite what you mean.\n\nIf you are completely sure that a variable is a boolean (either it has not been passed into your scope or you have checked it yourself), it is acceptable to leave out the `=== true`, as to put it in would be barbarous.\n\nComplex conditionals should be assigned to a descriptive variable.\n\nA common source of errors occurs when a developer writes a chain of if/else if/else if's and leaves out an else, or they write a bunch of nested ifs, and one of the inner ifs misses an else.  What's worse is that it's difficult to tell from looking at the code afterwards whether the author intended the behaviour or not.  When writing nested if statements, inner if's or run-on ifs should always have else clauses with a comment if they are empty.\n\n*Wrong:*\n\n```javascript\nif (someComplexCondition) {\n\tif (someOtherComplexCondition) {\n\t\tdoSomething();\n\t}\n} else if (anotherConditon) {\n\tdoAnotherThing();\n}\n```\n\n*Right:*\n\n```javascript\nif (someComplexCondition) {\n\tif (someOtherComplexCondition) {\n\t\tdoSomething();\n\t} else {\n\t\t// no need to do anything here because of X, Y, Z\n\t}\n} else if (anotherConditon) {\n\tdoAnotherThing();\n} else {\n\t// no need to do anything here because of W, Q, R.\n}\n```\n\n\nCoercion\n--------\nCoercion is bad.  Avoid it.\n\n* Prefer `===` to `==`\n* Prefer `!==` to `!=`\n\nWhen writing code to change the type of a variable\n\n* Prefer `String(number)` to `number + ''`.\n* Prefer `Number(string)` to ` +string `.\n* Prefer `Boolean(string)` to `!!string `.\n\nThis does not create a new object, and it makes your code clearer.\n\nIt is acceptable to use coercion when appending to a string (e.g. for logging).\n\nUsually use the Math methods for rounding numbers to integers (e.g. `Math.floor`).  There are short forms (eg. `real|0`), which may be more performant but they are less descriptive and do the wrong thing with large numbers.\n\n\nFunctions\n---------\n\nGuarded returns at the top of a function are fine.  Other than that, balance the following two considerations:\n\n* Having lots of returns in a function makes it hard to follow.\n* Having deeply nested conditional statements in a function makes it hard to read.  Anything that shifts code to the right should be meaningful for that code.\n\nAvoid nested closures, they quickly become hard to follow.  They can often be replaced with bound calls to methods.\n\n\nNaming\n------\n\n`lowerCamelCase` for variables and properties.  `UpperCamelCase` for classes. `ALL_CAPS_WITH_UNDERSCORES` for constants.  Long names are better than wrong or confusing names, but bear in mind that names much over four words become hard to read in camel case.\n\nAvoid uncommon abbreviations or single character names.  Single character loop counters are acceptable, but always consider if you can be more descriptive.\n\nAvoid meaningless or generic names like 'obj', 'temp', 'data'.  Type names are better than generic names but are still bad and should be avoided; 'func', 'string', 'str', 'num'.\n\nNames should be in a single language for the entire codebase.  For us, this is English (although USAian or UKian spelling variants are acceptable outside of the public API).\n\nWe discourage Hungarian Notation, however collections should be named with plural forms and if something is a boolean, it should be obvious from the name (e.g. isSelected).  Clearly indicating variables containing DOM elements or regexes can help keep code clean too.\n\nAnything that could be referenced from code in another file but that should not be (e.g. private member variables) must indicate this by having their name prepended with an underscore.\n\n```javascript\nfuntion MyClass() {\n\tthis.publicMember = 23;\n\tthis._privateMember = 44;\n}\n```\n\nIf your method has a name beginning with 'get', it should not usually modify any state.  An exception is for values that are lazily initialised.\n\nUse Function Declaration not Function Expressions, i.e.\n\n```javascript\n// Good\nfuntion myFunc() {\n}\n\n// Bad\nvar myFunc = function() {};\n```\n\nReasoning is for consistency and named functions show up in stack traces with their names (although newer engines are able to name anonymous functions).\n\nConstructors\n------------\nRemember to call your superconstructor in your own constructor. e.g.\n\n```javascript\nfunction MyClass(arg1, arg2) {\n\tSuperClass.call(this, arg1);\n\t/* myclass construction code */\n}\n```\n\nA constructor should leave the class in a consistent state (i.e. it should establish the class invariants).  If it cannot then it must throw an Error.\n\nSpaces\n------\nPut one space after:\n\n* control statements: `if`, `while`, `for`, ...\n* last closing bracket that is followed by a curly opening bracket\n* commas in function arguments list or when calling a function with multiple arguments\n* semi colons in `for` loops\n* commas when declaring multiple variables (preferably put each variable in a new line)\n* commas when defining array literals\n* colons when defining object literals\n\nPut spaces around:\n\n* operators in logical expressions: `\u0026\u0026`, `||`, `===`, `\u003c`, ...\n* assignment operators\n* `?` and `:` in ternary expressions\n\nDon't use a space:\n\n* between function name and opening bracket when invoking a function\n* between unary operators (`++`, `--`) and the variable they are operating on\n* before colons in object literals\n* to align attribute values or assignment operators when declaring multiple variables\n\nTrailing white space characters must be removed. No tabs on empty lines, no spaces at end of lines, etc.\n\nRight:\n\n```javascript\nfunction myFoo(arg1, arg2, arg3) {\n\tvar bar;\n\tvar arr = [1, 2, 3],\n\t\tobj = {\n\t\t\tprop1: 'aaa',\n\t\t\tprop2: 'bbb'\n\t\t},\n\t\ti;\n\n\tif (arg1 === 'something') {\n\t\tbar = 'baz';\n\t} else {\n\t\tbar = 42;\n\t}\n\n\tfor (i = 0; i \u003c arg2; i++) {\n\t\tmyBar(i, arg3);\n\t}\n\n\ti++;\n\n\tconsole.log(i % 2 ? 'yes' : 'no');\n};\n```\n\nWrong:\n\n```javascript\nfunction myFoo (arg1,arg2,arg3){\n\tvar bar,i;\n\tvar arr=[1,2,3];\n\tvar obj={prop1:'aaa',prop2:'bbb'};\n\n\tif(arg1==='something'){\n\t\tbar='baz';\n\t}else{\n\t\tbar=42;\n\t}\n\n\tfor(i=0;i\u003carg2;i++){\n\t\tmyBar (i,arg3);\n\t}\n\n\ti ++;\n\n\tconsole.log(i%2?'yes':'no');\n};\n```\n\nPublic API\n----------\nUse JSDoc comments for anything part of the public API (i.e. may be used by code outside our own codebase).\n\nYour JSDoc comments should make a point of describing what happens if any of the arguments are null/undefined when the function is called, whether the function can ever return null/undefined, and under which circumstances errors will be thrown.\n\nMethods that are part of the public API should start by checking their preconditions (e.g. types of arguments, etc.) and throwing appropriate Errors if the preconditions are not met.\n\n\nErrors\n------\nThrow only objects that are instances of the generic `Error` type.\n\nCustom Error objects are fine, but must inherit from `Error`, and set the name property.  Where appropriate reuse the standard Error types, e.g. TypeError, RangeError.\n\nError messages should include all the kinds of things you might need to debug the issue.  For example, if something is the wrong type, your error message should say what type it is as well as what type it should be.\n\n\nRevision Control\n----------------\n\nDo not check in commented out code.  Remembering old versions of code is what the revision control system is for.  If there is code commented out and checked in then nobody knows why it's there.\n\nWrite good check-in comments.  Mention the issue title and ID, who worked on the issue and what they did.  If someone is confused by a line of code you wrote, they will look at your check-in comment.  Make it useful.\n\n\nBrowser Specific Code\n---------------------\n\nCode that must support IE8 is limited to the shimmable subset of ecmascript 5.\n\n*OK (shimmable):*\n\n```javascript\nvar boundFunction = func.bind(this);\nvar x = Object.create(prototypeForX);\nvar arr = [1, 2, 3].map(function(x) {return x * 2;});\n\n```\n\n*Wrong (not shimmable):*\n\n```javascript\nvar x = {};\nObject.defineProperty(x, 'fred', {\n\tget: function() {\n\t\tconsole.log('fred has been got');\n\t\treturn 23;\n\t}\n});\n\n```\n\nGeneral library code must not modify the prototype of other objects.  It is acceptable for application code or shim libraries to do this, but it is a step that should be taken carefully.\n\nPrefer feature detection over browser detection.  Wheverever possible, keep code that depends on the browser (e.g. uses the DOM or host objects not common to other js environments) separate from pure javascript.\n\n\nGeneral Hygiene\n---------------\n\nStrict mode is encouraged.  You do this by putting `'use strict';` at the top of your scope. If you wish to have classes in strict mode and not leak it into the global scope the recommended approach is to use an IIFE.\n\nDo not use the single var pattern, use a var for each variable, [reasoning is provided here.](http://danielhough.co.uk/blog/single-var-pattern-rant/)\n\nKeep your lines, methods, classes and files short (aim for \u003c100 characters, \u003c10 lines, \u003c200 lines).\n\nDo not use globals.  Avoid using singletons.\n\nActively look for ways to fail faster.\n\nUse jsHint with the [provided settings](https://raw.github.com/caplin/StyleGuide/gh-pages/.jshintrc).\n\nWrite your code to be testable and test it! Writing code that receives objects it needs rather than creating them can make the code easier to test.  If you find yourself writing 'new', double check that your code is as testable as it should be.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaplin%2Fstyleguide","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcaplin%2Fstyleguide","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaplin%2Fstyleguide/lists"}