How to achieve code specification

code-norm

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: {name: "name", age: 20}}, 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 = {usr1: {}, 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 ${name}`;
   }

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 {String} tag
// @return {Element} 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

Tags: Javascript React TypeScript

Posted on Wed, 13 Oct 2021 08:54:15 -0400 by ShadowIce