Why did you do it
There are many front-end development specifications in the target market, some are too old, some are too simple and one-sided. Aiming at these problems, tal Peiyou growth front-end team has sorted out the latest and complete front-end development specifications, including JS, CSS, HTML, lint, Vue, etc.
The meaning of doing it
- Improve the readability and maintainability of the code.
Statistics show that in a large and medium-sized project, the later maintenance cost of the code is much higher than the development cost. Therefore, improve the maintainability of the code and greatly reduce the maintenance cost of the project. - Realize the standardization of project R & D.
The current project R & D process is similar to the assembly line production mode of automobile and other industrial products. Through the development specification, it can be conducive to the standardization of R & D. - Reduce bug s and facilitate code review.
In the world of art, we advocate unrestrained, but in the world of code, we should promote development norms, which will reduce the number of bug s and reduce the troubleshooting time.
JS
1. Code style
1.1 coding format
JavaScript files are encoded in UTF-8 without BOM.
ps: UTF-8 coding has wider adaptability. BOM may cause unnecessary interference when using programs or tools to process files.
1.2 code indentation
Indent with 2 spaces
1.3 code space
1.3. 1. There is a space on both sides of a binary operator, and no space is allowed between a unary operator and an operand
// bad let a=12 a=b+c a ++ // good let a = 14 a = b + c a++
1.3. 2. There is a space before the opening curly bracket {at the beginning of the code block.
// bad if (condition){ } while (condition){ } function funcName(){ } // good if (condition) { } while (condition) { } function funcName() { }
1.3. 3. There is a space after the if / else / for / while / function / switch / do / try / catch / finally keyword.
// bad if(condition) { } while(condition) { } // good if (condition) { } while (condition) { }
1.3. 4. When an object is created, there is a space after: and no space before: in the attribute.
// bad var obj = { a : 1, b:2, c :3 } // good var obj = { a: 1, b: 2, c: 3 }
##### 1.3. 5. In function declaration, named function expression and function call, no space is allowed between function name and ().
// bad function funcName () { const func = function (){} funcName () // good function funcName() { } const funcName = function() { } funcName()
2. Variable declaration
2.1,const, let ,var
Try to use const let for all variables instead of var.
ps: this ensures that you cannot reassign references to avoid errors and incomprehensible code.
In addition, all const s and let s are grouped. If the keyword is not written, the variable will be exposed to the global context, which is likely to conflict with the existing variable. In addition, it is difficult to clarify the scope of the variable.
// bad var a = 1 // good const a = 1 const b = 2 let c = 3 let d = 4
2.2 reserved words
Do not use reserved words as the key value of objects, which will not run under IE8
// bad const a = { default: {}, // default is a reserved word common: {} } // good const a = { defaults: {}, common: {} }
2.3 quotation marks
Use single quotation marks for strings and try not to use double quotation marks.
ps: because most of the time we use strings. In particular, double quotation marks appear in html
// bad const a = "123" // good const a = '123'
2.4 semicolon problem
The following situations can end without a semicolon
When declaring variables, import, export, return, throw, break
ps: without semicolon, it is concise and clear, and according to ASI [automatic semiconductor insertion] mechanism, semicolon will be automatically inserted during parsing
// bad let a = 12; import xxx from 'aa'; return; throw new Error(err); break; // good let a = 12 import xxx from 'aa' return throw new Error(err) break
2.5 chain assignment
Do not chain assign variables, which will create hidden global variables
// bad let a = b = 2 // good let a = 2 let b = 2
2.6 redundant variables
Unused variables are not allowed. Declared but unused variables are usually errors made by incomplete refactoring. Such variables waste space in the code and cause trouble to readers
3. Create variable
3.1. Create object variables
Please use literal value to create
ps: less code, high readability and fast running speed
// bad const a = new Object() const b = new Array() // good const a = {} const b = []
3.2. Create function
Do not use the Function constructor to create a Function
ps: less code, high readability and fast running speed
// bad const add = new Function('a', 'b', 'return a + b') // good const func1 = function() {}
3.3. Create string variable
When the string is too long, it is recommended not to use the string connector newline \, but to use+
// bad const string = 'Good future\ It is a very good education company\ It's really very good' // good const str = 'Good future' + 'It is a very good education company' + 'It's really very good' Template strings are recommended when generating strings programmatically const test = 'test' // bad const str = 'a' + 'b' + test // good const str = `ab${test}`
4. Arrow function
4.1. When you have to use function expressions (such as passing anonymous functions), use arrow function markers
ps: it will create a version of the function executed in the context of this, which is usually what you want, and the syntax is more concise
// bad [1, 2, 3].map(function(x) { const y = x + 1 return x * y }) // good [1, 2, 3].map(x => { const y = x + 1 return x * y })
4.2 parentheses of parameters in arrow function
If the arrow function has only one parameter, it is not bracketed. The introduction is clear
// bad [1,2,3].map((x) => { const y = x + 1 return x * y }) // good [1,2,3].map(x => { const y = x + 1 return x * y })
4.3. If the function body contains only one statement of return expression without side effects, you can omit the curly braces and use the implicit return. Otherwise, keep the curly braces and use the return statement
// bad [1, 2, 3].map(number => { const nextNumber = number + 1 `A string containing the ${nextNumber}` }) // good [1, 2, 3].map(number => `A string containing the ${number}`)
5. Deconstruction assignment
ps: deconstruction can avoid creating temporary references to attributes
5.1 object deconstruction
When you need to use multiple properties of an object, use deconstruction assignment
// bad function getFullName(user) { const firstName = user.firstName const lastName = user.lastName return `${firstName} ${lastName}` } // good function getFullName({ firstName, lastName }) { return `${firstName} ${lastName}` }
5.2 array deconstruction
When you need to use multiple values of an array, use deconstruction assignment as well
const arr = [1, 2, 3, 4] // bad const first = arr[0] const second = arr[1] // good const [first, second] = arr
5.3 deconstruction of function return parameters
When the function needs to return multiple values, use the deconstruction of the object rather than the deconstruction of the array.
ps: in this way, you can add or change the attribute order at any time non destructively
// bad function doSomething() { return [top, right, bottom, left] } // If it is array deconstruction, the order of data needs to be considered when calling const [top, xx, xxx, left] = doSomething() // good function doSomething() { return { top, right, bottom, left } } // The order of data does not need to be considered at this time const { top, left } = doSomething()
5.4 default value of deconstruction
When deconstructing variables, increase the default value to prevent reading null values or undefined values
// bad const { a, b } = { a: 3 } // good const { a = 10, b = 1 } = { a: 3 }
6. Class & constructor
6.1. Use class to avoid directly operating prototype
ps: it is easy to cause global pollution, conflict and difficult to locate bug s.
// bad function Queue(contents = []) { this._queue = [..contents] } Queue.prototype.pop = function () { const value = this._queue[0] this._queue.splice(0, 1) return value } // good class Queue { constructor(contents = []) { this._queue = [...contents] } pop() { const value = this._queue[0] this._queue.splice(0, 1) return value } }
6.2. Use extensions to implement inheritance
ps advantages: it is clear and convenient, and it is a way of prototype inheritance that will not destroy the built-in implementation of instanceof
// bad const inherits = require('inherits') function PeekableQueue(contents) { Queue.apply(this, contents) } inherits(PeekableQueue, Queue) PeekableQueue.prototype.peek = function () { return this.queue[0] } // good class PeekableQueue extends Queue { peek () { return this.queue[0] } }
7. Object properties
7.1. Preferred use To access object properties
ps: the advantage is simplicity and convenience
const joke = { name: 'haha', age: 28 } // bad const name = joke['name'] // good const name = joke.name
7.2. Only []
const luke = { jedi: true, age: 28, 12: 'num' } function getProp(prop) { return luke[prop] } const isJedi = getProp('jedi')
8. Conditional operation
8.1. Use = = = and== Not = = and=
const name = 'test' // bad if (name == 'test') { // ... } // good if (name === 'test') { // ... }
8.2. Use concise expressions as much as possible
const name = '' // bad if (name === '') { // ...... } // good if (!name) { // ...... }
8.3. If there is no statement after the else block in the function or global, else can be deleted
// bad function getName() { if (name) { return name; } else { return 'unnamed'; } } // good function getName() { if (name) { return name; } return 'unnamed'; }
9,eval()
The eval method compares evil, so our Convention prohibits the use of this method
ps: eval will cause xss attack; eval will interfere with the scope chain, etc. it is not recommended to use eval in code
10. Do not modify the prototype of built-in objects
11. Variable naming rules
11.1 small hump format for conventional variables
let userInfo = {}
11.2. Global constants are connected by capital letters and multiple letters are underlined
const MATH_PI = 3.14
11.3. Private variables in the class begin with an underscore
11.4 the class name is in the form of large hump
class UserInfo {}
11.5. Common function names are in small hump format
function getUserInfo() {}
11.6 the enumeration variables are in the form of large hump, and the enumeration attributes are capitalized with all letters and separated by underscores between words
const Week = { MONDAY: 0, TUESDAY: 1 }
11.7 for boolean variables, it is recommended to start with is or has [recommended]
// General variable const loginStatus = 0 // Global constant const COUNT = 0 // Global constant const MAX_NUM = 99 // Class declaration class Point { constructor(name, age) { this._name = name this._age = age } toString() { return '(' + this._name + ', ' + this._age + ')' } } // Ordinary function function stringFormat(source) { } // Enumerating variables const TargetState = { READING: 1, READED: 2, APPLIED: 3 } // Variables of type boolean const isReady = false const hasSelected = false
12. & & and||
Binary Boolean operators are short circuitable and will only evaluate to the last term if necessary.
// a + + does not execute let x = false let a = 1 let y = x && a++
13. Annotation specification
13.1 single line notes
Exclusive line, / / followed by a space, and the indentation is consistent with the code described in the next line.
13.2 multiline notes
Try to avoid using / */ Such a multiline comment. When there are multiple lines of comment content, multiple single line comments are used.
13.3 format of documented notes
Use @ key desc format to write
Common keywords are:
@author author @param parameter @example Example @link link @namespace Namespace @requires Dependent module @return Return value @version Version number
The type definitions of annotated param s start with {and end with}
Types of commonly used param s: {String}, {Number}, {Boolean}, {Object}, {Function}, {RegExp}, {Array}, {Date}
13.4 notes to functions / methods
Contains the description of the function. If there are parameters and return values, they must be identified with comments
/** * @desc Function description * @param {String} p1 Description of parameter 1 * @param {String} p2 Description of parameter 2 * @param {Number=} p3 Description of parameter 3 (optional) * @return {Object} Return value description */ function foo(p1, p2, p3) { return { p1: p1, p2: p2, p3: p3 } }