with TypeScript Based language
type
Basic type
-
When assigning a value to a base type, the value of the type should be used directly
Foundation types include string, number, boolean, null, undefined, symbol
Complex type
-
Complex type must be const (constant)
-
Complex type assignment is actually a reference to an address
Complex types include object, array, function, enum(TypeScript)
state
-
Do not use var
-
Try to use const
-
Use less let
var yes js The variable declaration in the syntax is a keyword, but it has several disadvantages. First, it has no block level scope, and second var A variable is declared. The variable itself means that the structure is variable. Any data with variable structure itself means instability and defects in the code design itself.
object
- Create an object using literals
// Wrong way const data = new Object(); // The right way const data = {};
- Attribute value abbreviation
const name = "abc"; // Wrong way const usr = { name: name } // The right way const usr = { name }
- When you need to copy an object, use the... Extension operator instead of Object.assign. When deconstructing assignment to obtain several attributes of the object, use the rest operator, which is also
// very bad const original = { a: 1, b: 2 }; const copy = Object.assign(original, { c: 3 }); delete copy.a; // so does this change the original // 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 }
In general, copies of values are used for react of state Setting of complex properties. For example, state = { usr1: }, If it needs to be modified separately usr1 of name Property, you must first usr1 A light copy_usr1,Then modify_usr1 of name Property, and then_usr1 The value of is passed setState Update to state Medium usr1 Come on.
array
- Literal assignment
// bad const items = new Array(); // good const items = [];
- Use the push of Array to add a value to the Array instead of subscript directly
const items = []; // bad item[item.length] = "abc"; // good items.push("abc");
-
Object to array
The back-end transfer output is divided into arrays and Map In both cases, the array itself has traversal properties, but Map Is a special format, such as result = , usr2: {}, usr3: {}},among usr1, usr2,...All have exactly the same structure. At this time, we can result Convert to an array, and the value of the array is result Properties of
interface IUsr{ name: string; age: number } interface IUsrMap{ [name: string]: IUsr } const result: IUsrMap = { usr1: { name: "usr_1", age: 10 }, usr2: { name: "usr_2", age: 11 } } const result_arr: IUsr[] = [...result];
- If an array has many rows, wrap the row before the [after and] of the array
// bad const arr = [ [0, 1], [2, 3], [4, 5], ]; const objectInArray = [{ id: 1, }, { id: 2, }]; const numberInArray = [ 1, 2, ]; // good const arr = [[0, 1], [2, 3], [4, 5]]; const objectInArray = [ { id: 1, }, { id: 2, }, ]; const numberInArray = [ 1, 2, ];
- Use string templates instead of + to splice strings
// bad function sayHi(name: string){ return "Hi " + name; } // bad function sayHi(name: string){ return ["Hi", name].join(" "); } // bad function sayHi(name: string){ return `Hi ${ name }`; } // good function sayHi(name: string){ return `Hi $`; }
function
-
Use named function expressions instead of function declarations
The scope of function declaration will be improved, which reduces the readability and maintainability of code. If you find that a function is large and complex, which hinders the understanding of other parts of the file, it may be time to separate the function into a module.
// bad function foo() { // ... } // bad const foo = function () { // ... }; // good const short = function longUniqueMoreDescriptiveLexicalFoo() { // ... };
- Never name parameters with arguments. Its priority is higher than the arguments object of each function scope, so it will cause the arguments value of the function to be overwritten.
// bad function foo(name, options, arguments) { // ... } // good function foo(name, options, args) { // ... }
- Use default parameter syntax instead of reassigning parameters in functions
// really bad function handleThings(opts) { // Although you want to write this, this will bring some subtle bug s // If the value of opts is false, it will be assigned {} opts = opts || {}; // ... } // still bad function handleThings(opts) { if (opts === void 0) { opts = {}; } // ... } // good function handleThings(opts = {}) { // ... }
- Side effects need to be avoided when using default parameters
var b = 1; // bad function count(a = b++) { console.log(a); } count(); // 1 count(); // 2 count(3); // 3 count(); // 3
If you need to modify the effect of a certain value during execution, for example, click accumulation and click subtraction, you can construct a class and modify it directly in the method of the class this The following tag attributes achieve this effect
- Put the default parameter assignment last
// bad function handleThings(opts = {}, name) { // ... } // good function handleThings(name, opts = {}) { // ... }
In fact, the call results of the former function and the latter function are completely different, because the parameter assignment of the function is in the order from left to right. If only one parameter is passed, it will be given in the first function opts Variable, but the second function gives name Variable.
- Do not re assign (*) to the parameter
// bad function f1(a) { a = 1; // ... } function f2(a) { if (!a) { a = 1; } // ... } // good function f3(a) { const b = a || 1; // ... } function f4(a = 1) { // ... }
because js It is an explanatory language, so even if you directly modify the parameters of a function within a function, you will not throw errors directly during execution, but the behavior of modifying parameters destroys the stability of the class function itself. The function itself should have three stability characteristics, 1.Functions are invariant after declaration. Multiple functions require multiple declarations and are called separately instead of modifying the declared functions to achieve the purpose. two.The parameters of the function cannot be modified. Generally speaking, if we need to generate a new data structure with the help of the current parameters, we should directly construct a new variable instead of modifying the original variable. 3.The function of the function is pure and refined. The more complex the single execution process of the function, the worse the corresponding stability and readability. When you need to complete a complex function, you should first consider how to split the function and then combine the function to achieve the effect. In short, the shorter the number of lines of each function, the better. There is no requirement for the number. There are three functions with 40 lines>2 60 line parameters>120 A single function of the line. (this is actually an optimization method of the function)
- If you want to use anonymous functions as callbacks, you'd better use the arrow function
// 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; }); // best [1, 2, 3].map((x) => x*(x + 1));
Classes and constructors
- Always use class to avoid direct manipulation of prototype
// 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; } }
-
Use extensions to implement inheritance. Do not directly operate on prototype
-
Method can return this to implement the method chain
// good class Jedi { jump() { this.jumping = true; return this; } setHeight(height) { this.height = height; return this; } } const luke = new Jedi(); luke.jump().setHeight(20);
iterator
-
Don't use iterators. Replace for in and for of with JavaScript higher-order functions
According to the immutability principle, it is easier to deal with the return value of pure functions than with side effects. Iterative method of array: map() / every() / filter() / find() / findIndex() / reduce() / some() / ... Object processing method: Object.keys() / Object.values() / Object.entries() To generate an array so that you can traverse the object Object conversion array reference-> The objects above are converted to arrays
const numbers = [1, 2, 3, 4, 5]; // bad let sum = 0; for (let num of numbers) { sum += num; } sum === 15; // good let sum = 0; numbers.forEach(num => sum += num); sum === 15; // best (use the functional force) const sum = numbers.reduce((total, num) => total + num, 0); sum === 15; // bad const increasedByOne = []; for (let i = 0; i < numbers.length; i++) { increasedByOne.push(numbers[i] + 1); } // good const increasedByOne = []; numbers.forEach(num => increasedByOne.push(num + 1)); // best (keeping it functional) const increasedByOne = numbers.map(num => num + 1);
attribute
- Use point symbols to access properties
const luke = { jedi: true, age: 28, }; // bad const isJedi = luke['jedi']; // good const isJedi = luke.jedi;
- Use square brackets [] when the obtained property is a variable
const luke = { jedi: true, age: 28, }; function getProp(prop) { return luke[prop]; } const isJedi = getProp('jedi');
variable
-
Always declare variables with const or let
-
Each variable uses a const or let separately
-
Do not use continuous variable assignments
for example let a = b = c = 1 This use is wrong
-
Unused variables are not allowed
-
It is forbidden to use duplicate and meaningless variable names in the same region
This will make your code more difficult to read. One of the characteristics of good code is simplicity, so don't use variable names a lot a,b,c In this way, you can try to[Data meaning+data type],Such as site configuration-siteConfig,If it is a multi site configuration, it is-siteConfigList,Of course, the most important thing is to annotate this variable
Compare and equal
-
Use = = = for comparison
-
For possible null attributes, use if(value) to execute the existing option, or if(!value) to execute the nonexistent option
-
Objects => true
-
Undefined => false
-
Null => false
-
Booleans => the value of the boolean
-
Numbers
- 0, -0, or NaN => false
- Other = > true
-
Strings
- '' => false
- Other = > true
-
In switch case, create a block (such as let, const,function, and class) with braces in case and default clauses
// bad switch (foo) { case 1: let x = 1; break; case 2: const y = 2; break; case 3: function f() { // ... } break; default: class C {} } // good switch (foo) { case 1: { let x = 1; break; } case 2: { const y = 2; break; } case 3: { function f() { // ... } break; } case 4: bar(); break; default: { class C {} } }
switch case In grammar, it's best not to use it directly return Direct return, using return Directly interrupting the whole function will lead to incomplete flow of the whole function, so it is best switch Just branch, and then directly break,If you need to return, directly in the whole switch Add after statement return
notes
- Multiline comment with / * **/
// bad // make() returns a new element // based on the passed in tag name // // @param tag // @return element function make(tag) { // ... return element; } // good /** * make() returns a new element * based on the passed-in tag name */ function make(tag) { // ... return element; }
- Add a space at the beginning of all comments for easy reading
// bad //is current tab const active = true; // good // is current tab const active = true; // bad /** *make() returns a new element *based on the passed-in tag name */ function make(tag) { // ... return element; } // good /** * make() returns a new element * based on the passed-in tag name */ function make(tag) { // ... return element; }
Naming convention
- Avoid naming with one letter and make your naming more semantic
- Name your objects, functions, and instances with camelCase
- Do not save a reference to this, use the arrow function or hard bind
// bad function foo() { const self = this; return function () { console.log(self); }; } // bad function foo() { const that = this; return function () { console.log(that); }; } // good function foo() { return () => { console.log(this); }; }
-
The file name should exactly match the name of the default export
-
All uppercase letters define constants to export
const ADMIN = "admin" This means ADMIN Is a constant that is used for multiple references at once
common problem
-
Too many component lines (> 300)
-
The return value type of the function is consistent (except null)
1.If the execution result of the function has a return value under certain circumstances, please add the return value to the results of all execution branches 2.If the execution fails (such as network request), please add the return value null 3.The type of return value is consistent. If a branch returns true,Then all return values can only be true|false,Of course, if it is a request for data, it can be returned when the request fails null
-
Do not add any meaningless return value. When judging whether a function needs a return value, the first thing to do is to think about what problems exist if the return value is not added, and whether this problem can be solved without the return value