One, foreword

The purpose of a specification is to write high quality code that makes us and our colleagues happy every day and happy to work together.

A word of caution: These specifications don’t make you a good engineer right away, and sticking to them for a long time doesn’t mean you won’t make mistakes in the future. A journey of a thousand miles begins with a single step. We need to conduct frequent code reviews with our colleagues to keep optimizing our code. Don’t be afraid of the effort it takes to improve the quality of your code.

Second, the naming

2.1 Project Naming

Use lowercase letters and separate them with a hyphen (or a hyphen).

Examples: taro-v2ex-hooks, taro_v2ex_hooks

2.2 Directory Naming

Use all lowercase ways, delimited by a hyphen (or hyphen). When there is a complex structure, use the plural naming method, and do not use plural abbreviations.

Example: styles, utils, img, demo_styles

Warm tip: unified style, do not use a hyphen for a while, while the underscore.

2.3 Naming rigor

Code naming is strictly prohibited to use pinyin and English mixed way, pure pinyin should also be avoided. International common names may be regarded as English.

Example: Shenzhen, RMB

Example: getGuoJiaName ()

Three, HTML

3.1 grammar

  • Use 2 Spaces (or 4 Spaces) for indentation
  • Nested nodes should be indented
  • Semantic tags are preferred
  • On attributes, use double quotes

Ex. :

<! DOCTYPEhtml>
<html>
    <head>
        <title>Page title</title>
    </head>
    <body>
    	<header></header>
        <img src="images/company_logo.png" alt="Company">
        <h1 class="hello-world">Hello, world!</h1>
		<footer></footer>
    </body>
</html>
Copy the code

3.2 Attribute Order

Attributes should appear in a specific order to ensure legibility.

  • class
  • id
  • name
  • data-*
  • src, for, type, href, value , max-length, max, min, pattern
  • placeholder, title, alt
  • aria-*, role
  • required, readonly, disabled

Classes are designed for highly reusable components, so they should come first.

Id is more specific and should be used sparingly, so put it second.

Example: < a class = “…” id=”…” data-modal=”toggle” href=”#”>Example link

Four, CSS,

4.1 named

  • Class names are in lowercase letters, separated by hyphens (or underscores)
  • The ID is named in a hump format
  • Variables, functions, blends, and placeholder names in SCSS are humped

Ex. :

#myApp {
    font-weight: 400;
}

.hello-world {
    font-size: 24px;
}
Copy the code

4.2 the blank space

  • Attribute values before
  • The selector>.+.~Before and after
  • {
  • ! important!
  • @elseBefore and after
  • Attribute value.
  • annotation/ *And after* /

Ex. :

/* good */
.element {
    color: red ! important;
    background-color: rgba(0.0.0.5);
}

@if{... }@else{... }Copy the code

4.3 a blank line

  • Leave a blank line at the end of the file
  • }This is preferably followed by a blank line that includes the nested rules in SCSS
  • Appropriate blank lines are required between properties, as shown in property declaration order

Ex. :

.element{... }.dialog {
    color: red; &:after { ... }}Copy the code

4.4 a newline

  • {And after}
  • Each property gets its own row
  • Delimiter for multiple rules.

Ex. :

.element {
    color: red;
    background-color: black;
}

.main..dialog{... }Copy the code

4.5 Property declaration order

Related attribute declarations are grouped in the order on the right, with a blank line between the groups.

Ex. :

.declaration-order {
    display: block;
    float: right;

    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 100;

    border: 1px solid #e5e5e5;
    border-radius: 3px;
    width: 100px;
    height: 100px;

    font: normal 13px "Helvetica Neue", sans-serif;
    line-height: 1.5;
    text-align: center;

    color: # 333;
    background-color: #f5f5f5;

    opacity: 1;
}
Copy the code

Here is the order of recommended attributes:

[["display"."visibility"."float"."clear"."overflow"."overflow-x"."overflow-y"."clip"."zoom"
    ],
    [
        "table-layout"."empty-cells"."caption-side"."border-spacing"."border-collapse"."list-style"."list-style-position"."list-style-type"."list-style-image"
    ],
    [
        "-webkit-box-orient"."-webkit-box-direction"."-webkit-box-decoration-break"."-webkit-box-pack"."-webkit-box-align"."-webkit-box-flex"
    ],
    [
        "position"."top"."right"."bottom"."left"."z-index"
    ],
    [
        "margin"."margin-top"."margin-right"."margin-bottom"."margin-left"."-webkit-box-sizing"."-moz-box-sizing"."box-sizing"."border"."border-width"."border-style"."border-color"."border-top"."border-top-width"."border-top-style"."border-top-color"."border-right"."border-right-width"."border-right-style"."border-right-color"."border-bottom"."border-bottom-width"."border-bottom-style"."border-bottom-color"."border-left"."border-left-width"."border-left-style"."border-left-color"."-webkit-border-radius"."-moz-border-radius"."border-radius"."-webkit-border-top-left-radius"."-moz-border-radius-topleft"."border-top-left-radius"."-webkit-border-top-right-radius"."-moz-border-radius-topright"."border-top-right-radius"."-webkit-border-bottom-right-radius"."-moz-border-radius-bottomright"."border-bottom-right-radius"."-webkit-border-bottom-left-radius"."-moz-border-radius-bottomleft"."border-bottom-left-radius"."-webkit-border-image"."-moz-border-image"."-o-border-image"."border-image"."-webkit-border-image-source"."-moz-border-image-source"."-o-border-image-source"."border-image-source"."-webkit-border-image-slice"."-moz-border-image-slice"."-o-border-image-slice"."border-image-slice"."-webkit-border-image-width"."-moz-border-image-width"."-o-border-image-width"."border-image-width"."-webkit-border-image-outset"."-moz-border-image-outset"."-o-border-image-outset"."border-image-outset"."-webkit-border-image-repeat"."-moz-border-image-repeat"."-o-border-image-repeat"."border-image-repeat"."padding"."padding-top"."padding-right"."padding-bottom"."padding-left"."width"."min-width"."max-width"."height"."min-height"."max-height"
    ],
    [
        "font"."font-family"."font-size"."font-weight"."font-style"."font-variant"."font-size-adjust"."font-stretch"."font-effect"."font-emphasize"."font-emphasize-position"."font-emphasize-style"."font-smooth"."line-height"."text-align"."-webkit-text-align-last"."-moz-text-align-last"."-ms-text-align-last"."text-align-last"."vertical-align"."white-space"."text-decoration"."text-emphasis"."text-emphasis-color"."text-emphasis-style"."text-emphasis-position"."text-indent"."-ms-text-justify"."text-justify"."letter-spacing"."word-spacing"."-ms-writing-mode"."text-outline"."text-transform"."text-wrap"."-ms-text-overflow"."text-overflow"."text-overflow-ellipsis"."text-overflow-mode"."-ms-word-wrap"."word-wrap"."-ms-word-break"."word-break"
    ],
    [
        "color"."background"."filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"."background-color"."background-image"."background-repeat"."background-attachment"."background-position"."-ms-background-position-x"."background-position-x"."-ms-background-position-y"."background-position-y"."-webkit-background-clip"."-moz-background-clip"."background-clip"."background-origin"."-webkit-background-size"."-moz-background-size"."-o-background-size"."background-size"
    ],
    [
        "outline"."outline-width"."outline-style"."outline-color"."outline-offset"."opacity"."filter:progid:DXImageTransform.Microsoft.Alpha(Opacity"."-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha"."-ms-interpolation-mode"."-webkit-box-shadow"."-moz-box-shadow"."box-shadow"."filter:progid:DXImageTransform.Microsoft.gradient"."-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient"."text-shadow"
    ],
    [
        "-webkit-transition"."-moz-transition"."-ms-transition"."-o-transition"."transition"."-webkit-transition-delay"."-moz-transition-delay"."-ms-transition-delay"."-o-transition-delay"."transition-delay"."-webkit-transition-timing-function"."-moz-transition-timing-function"."-ms-transition-timing-function"."-o-transition-timing-function"."transition-timing-function"."-webkit-transition-duration"."-moz-transition-duration"."-ms-transition-duration"."-o-transition-duration"."transition-duration"."-webkit-transition-property"."-moz-transition-property"."-ms-transition-property"."-o-transition-property"."transition-property"."-webkit-transform"."-moz-transform"."-ms-transform"."-o-transform"."transform"."-webkit-transform-origin"."-moz-transform-origin"."-ms-transform-origin"."-o-transform-origin"."transform-origin"."-webkit-animation"."-moz-animation"."-ms-animation"."-o-animation"."animation"."-webkit-animation-name"."-moz-animation-name"."-ms-animation-name"."-o-animation-name"."animation-name"."-webkit-animation-duration"."-moz-animation-duration"."-ms-animation-duration"."-o-animation-duration"."animation-duration"."-webkit-animation-play-state"."-moz-animation-play-state"."-ms-animation-play-state"."-o-animation-play-state"."animation-play-state"."-webkit-animation-timing-function"."-moz-animation-timing-function"."-ms-animation-timing-function"."-o-animation-timing-function"."animation-timing-function"."-webkit-animation-delay"."-moz-animation-delay"."-ms-animation-delay"."-o-animation-delay"."animation-delay"."-webkit-animation-iteration-count"."-moz-animation-iteration-count"."-ms-animation-iteration-count"."-o-animation-iteration-count"."animation-iteration-count"."-webkit-animation-direction"."-moz-animation-direction"."-ms-animation-direction"."-o-animation-direction"."animation-direction"
    ],
    [
        "content"."quotes"."counter-reset"."counter-increment"."resize"."cursor"."-webkit-user-select"."-moz-user-select"."-ms-user-select"."user-select"."nav-index"."nav-up"."nav-right"."nav-down"."nav-left"."-moz-tab-size"."-o-tab-size"."tab-size"."-webkit-hyphens"."-moz-hyphens"."hyphens"."pointer-events"]]Copy the code

4.6 Property shorthand

Property abbreviations require you to be very clear about the correct order of property values, and in most cases you do not need to set all the values contained in the property abbreviations, so it is recommended to declare them as separate as possible for clarity.

Common abbreviations for properties include:

  • font
  • background
  • transition
  • animation

Ex. :

.element {
    transition-delay: 2s;
    transition-timing-function: linear;
    transition-duration: 1s;
    transition-property: opacity;
}
Copy the code

Five, JavaScript,

5.1 variable

5.1.1 Use meaningful and readable variable names

Example:

var yyyymmdstr = moment().format('YYYY/MM/DD');
Copy the code

Is:

var yearMonthDay = moment().format('YYYY/MM/DD');
Copy the code

5.1.2 Use ES6 const to define constants

The “constant” defined with “var” in the counter example is mutable.

When a constant is declared, it should remain immutable throughout the program.

Example:

var FIRST_US_PRESIDENT = "George Washington";
Copy the code

Is:

const FIRST_US_PRESIDENT = "George Washington";
Copy the code

5.1.3 Use easy-to-retrieve names

We need to read more code than we write, and it’s important to make it readable and easy to retrieve. Reading code with obscure variable names can be a pretty bad experience for the reader. Make your variable names easy to retrieve.

Example:

// What is 525600?
for (var i = 0; i < 525600; i++) {
  runCronJob();
}
Copy the code

Is:

const MINUTES_IN_A_YEAR = 525600;
for (var i = 0; i < MINUTES_IN_A_YEAR; i++) {
  runCronJob();
}
Copy the code

5.1.4 Explicit is better than implicit

Example:

var locations = ['Austin'.'New York'.'San Francisco'];
locations.forEach((l) = >{ doStuff(); doSomeOtherStuff(); . . .// What is l?
  dispatch(l);
});
Copy the code

Is:

var locations = ['Austin'.'New York'.'San Francisco'];
locations.forEach((location) = >{ doStuff(); doSomeOtherStuff(); . . . dispatch(location); });Copy the code

5.1.5 Avoid meaningless conditional judgment

Example:

function createMicrobrewery(name) {
  var breweryName;
  if (name) {
    breweryName = name;
  } else {
    breweryName = 'Hipster Brew Co.'; }}Copy the code

Is:

function createMicrobrewery(name) {
  var breweryName = name || 'Hipster Brew Co.'
}
Copy the code

5.2 the function

5.2.1 Function parameters

It is necessary to limit the number of function arguments (ideally no more than two) to make it easier to test the function. Too many parameters make it difficult to test the parameters of a function with valid test cases.

Functions with more than three arguments should be avoided. Usually, more than two arguments means that the function is too complex and you need to re-optimize your function. When you do need multiple parameters, in most cases you can consider wrapping those parameters into a single object.

When you need more than one parameter, you can use one object instead.

Example:

function createMenu(title, body, buttonText, cancellable) {... }Copy the code

Is:

var menuConfig = {
  title: 'Foo'.body: 'Bar'.buttonText: 'Baz'.cancellable: true
}

function createMenu(menuConfig) {... }Copy the code

5.2.2 Unitary function

This is one of the most important principles of software functionality.

Functions with more than one function make it difficult to refactor, test, and understand. Single-function functions are easy to refactor and make your code cleaner.

Example:

function emailClients(clients) {
  clients.forEach(client= > {
    let clientRecord = database.lookup(client);
    if(clientRecord.isActive()) { email(client); }}); }Copy the code

Is:

function emailClients(clients) {
  clients.forEach(client= > {
    emailClientIfNeeded(client);
  });
}

function emailClientIfNeeded(client) {
  if(isClientActive(client)) { email(client); }}function isClientActive(client) {
  let clientRecord = database.lookup(client);
  return clientRecord.isActive();
}
Copy the code

5.2.3 Removing duplicate code

Never, never, never have duplicate code under any loop.

This is pointless and potentially dangerous. Repetitive code means more than one change is needed when the logic changes. The weak type of JS makes functions more universal. Take advantage of it.

Example:

function showDeveloperList(developers) {
  developers.forEach(developer= > {
    var expectedSalary = developer.calculateExpectedSalary();
    var experience = developer.getExperience();
    var githubLink = developer.getGithubLink();
    var data = {
      expectedSalary: expectedSalary,
      experience: experience,
      githubLink: githubLink
    };

    render(data);
  });
}

function showManagerList(managers) {
  managers.forEach(manager= > {
    var expectedSalary = manager.calculateExpectedSalary();
    var experience = manager.getExperience();
    var portfolio = manager.getMBAProjects();
    var data = {
      expectedSalary: expectedSalary,
      experience: experience,
      portfolio: portfolio
    };

    render(data);
  });
}
Copy the code

Is:

function showList(employees) {
  employees.forEach(employee= > {
    var expectedSalary = employee.calculateExpectedSalary();
    var experience = employee.getExperience();
    var portfolio;

    if (employee.type === 'manager') {
      portfolio = employee.getMBAProjects();
    } else {
      portfolio = employee.getGithubLink();
    }

    var data = {
      expectedSalary: expectedSalary,
      experience: experience,
      portfolio: portfolio
    };

    render(data);
  });
}
Copy the code

5.2.4 Using default Parameters to simplify code

Example:

function writeForumComment(subject, body) {
  subject = subject || 'No Subject';
  body = body || 'No text';
}
Copy the code

Is:

function writeForumComment(subject = 'No subject', body = 'No text') {... }Copy the code

5.2.5 Do not use Flag as a function parameter

This usually means that the functionality of the function has been broken. You should think about dividing the function again.

Example:

function createFile(name, temp) {
  if (temp) {
    fs.create('./temp/' + name);
  } else{ fs.create(name); }}Copy the code

Is:

function createTempFile(name) {
  fs.create('./temp/' + name);
}

function createFile(name) {
  fs.create(name);
}
Copy the code

5.2.6 Use functional programming

Functional programming is cleaner and easier to test. Use this style whenever possible.

Example:

const programmerOutput = [
  {
    name: 'Uncle Bobby'.linesOfCode: 500
  }, {
    name: 'Suzie Q'.linesOfCode: 1500
  }, {
    name: 'Jimmy Gosling'.linesOfCode: 150
  }, {
    name: 'Gracie Hopper'.linesOfCode: 1000}];var totalOutput = 0;

for (var i = 0; i < programmerOutput.length; i++) {
  totalOutput += programmerOutput[i].linesOfCode;
}
Copy the code

Is:

const programmerOutput = [
  {
    name: 'Uncle Bobby'.linesOfCode: 500
  }, {
    name: 'Suzie Q'.linesOfCode: 1500
  }, {
    name: 'Jimmy Gosling'.linesOfCode: 150
  }, {
    name: 'Gracie Hopper'.linesOfCode: 1000}];var totalOutput = programmerOutput
  .map((programmer) = > programmer.linesOfCode)
  .reduce((acc, linesOfCode) = > acc + linesOfCode, 0);
Copy the code

5.2.7 Avoid over-optimization

Modern browsers automatically optimize code at run time. Sometimes human optimization of code can be a waste of time.

There are a lot of areas that really need to be optimized

Example:

// Len is used here because in older browsers, using the positive example would cause the value of list.length to be evaluated twice each time.
// In modern browsers, the optimization is done automatically, and this behavior is not necessary
for (var i = 0, len = list.length; i < len; i++) {
  // ...
}
Copy the code

Is:

for (var i = 0; i < list.length; i++) {
  // ...
}
Copy the code

5.3 concurrent

5.3.1 Replace the callback with Promises

Callbacks are not clean enough and can cause a lot of nesting. ES6 has Promises built into it. Use them.

Example:

require('request').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin'.function(err, response) {
  if (err) {
    console.error(err);
  }
  else {
    require('fs').writeFile('article.html', response.body, function(err) {
      if (err) {
        console.error(err);
      } else {
        console.log('File written'); }})}})Copy the code

Is:

require('request-promise').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
  .then(function(response) {
    return require('fs-promise').writeFile('article.html', response);
  })
  .then(function() {
    console.log('File written');
  })
  .catch(function(err) {
    console.error(err);
  })
Copy the code

5.3.2 Async/Await is a better option than Promises

Promises are a better option than callbacks, but async and await in ES7 are better than Promises.

Use ES7 features instead of Promises where possible.

Example:

require('request-promise').get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin')
  .then(function(response) {
    return require('fs-promise').writeFile('article.html', response);
  })
  .then(function() {
    console.log('File written');
  })
  .catch(function(err) {
    console.error(err);
  })
Copy the code

Is:

async function getCleanCodeArticle() {
  try {
    var request = await require('request-promise')
    var response = await request.get('https://en.wikipedia.org/wiki/Robert_Cecil_Martin');
    var fileHandle = await require('fs-promise');

    await fileHandle.writeFile('article.html', response);
    console.log('File written');
  } catch(err) {
    console.log(err); }}Copy the code

5.4 annotations

5.4.1 Annotate only code that has certain complexity of business logic

Comments are not necessary. Good code is easy to read without too many unnecessary comments.

Example:

function hashIt(data) {
  // The hash
  var hash = 0;

  // Length of string
  var length = data.length;

  // Loop through every character in data
  for (var i = 0; i < length; i++) {
    // Get character code.
    var char = data.charCodeAt(i);
    // Make the hash
    hash = ((hash << 5) - hash) + char;
    // Convert to 32-bit integerhash = hash & hash; }}Copy the code

Is:

function hashIt(data) {
  var hash = 0;
  var length = data.length;

  for (var i = 0; i < length; i++) {
    var char = data.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;

    // Convert to 32-bit integerhash = hash & hash; }}Copy the code

5.4.2 Don’t leave commented out code in the code base

Version control exists for a reason. Keep the old code in your history.

Example:

doStuff();
// doOtherStuff();
// doSomeMoreStuff();
// doSoMuchStuff();
Copy the code

Is:

doStuff();
Copy the code

6. Reference articles

  • clean-code-javascript
  • Code Guide by @AlloyTeam

Thank you,

  • If this article helped you, just give it a like! Thanks for reading.