How to write more elegant code - JavaScript articles

How to write more elegant code - JavaScript articles ## Title

Some people say that good code is like a poem, elegant and connotative.
In daily development, when maintaining other people's old code, do you always feel that the logic is confusing and you can't get started, just like a mountain of shit? Fixing a BUG is like trying to pull another pile on this shit mountain... Today, from the perspective of daily development, we will talk about how to make our code clearer, easier to maintain, and make others look more realistic .

variable naming

To write good code, variable naming is very important. We try our best to use expressive words. If English is not good, we often use translation software to ensure that there are no wrong words. The editor can install related spell checking and translation plug-ins.
Do not abbreviate/abbreviate words unless they are recognized as being abbreviated/abbreviated as such. Doing so leads to loss of readability and ambiguous meaning. Counter-example: Association ass, StringBuilder sb
ordinary variable names use nouns and noun phrases.
For example, boolean names such as value, options, fileText, columnName, etc., if it means "is it" use is..., if it means "whether it is" use has..., if it means "can it" use can..., if it means "can it be how" use... able
function names are in verb/object order. For example, getUserInfo, insertRows, clearValue, etc.
Avoid using _ at the beginning, temp, my, etc. to name temporary variables. Temporary variables are also meaningful. These will increase the noise when reading code
to avoid meaningless naming. Every name you name must be can express meaning. Such as userInfo, clickCount counter example info, count

code structure

A good code structure helps us maintain rational thinking and reduce mental burden.
use const definition

If there is no complicated logic, it is enough to use const, so that there is no need to worry about unexpected situations caused by variables being reassigned. When this pattern is written a lot, you will find that there are few places where let is used in the project.

// Bad
let result = false;
if (userInfo.age > 30) {
  result = true;
}
// Good
const result = userInfo.age > 30;

logical classification

In complex logic, related logic should be put together as much as possible, and blank lines should be inserted to separate them. Make the code structure look clear and concise.

return early

In the function, it is often encountered that the value of the variable is undefined. At this time, it is necessary to judge in advance and prevent the execution, avoid some unnecessary branches (no else), and make the code more refined.

if (!userInfo) {
  return;
}

if (!hasMoney) {
  return;
}
// 执行业务逻辑

elegant conditional judgment

Simply judge if + return to return in advance. Complex logic if else if noodle code is not elegant enough, want to use switch case? The actual situation seems to have little difference between the usage of if else and switch case.

// if else
if (status == 1) {
  console.log('processing');
} else if (status == 2) {
  console.log('fail');
} else if (status == 3) {
  console.log('success');
} else if (status == 4) {
  console.log('cancel');
} else {
  console.log('other');
}

// switch case
switch (status) {
  case 1:
    console.log('processing');
    break;
  case 2:
    console.log('fail');
    break;
  case 3:
    console.log('success');
    break;
  case 4:
    console.log('cancel');
    break;
  default:
    console.log('other');
    break;
}

In the above code, it can be seen that the switch case has more lines of code than the if else, and the break keyword is also essential. Don’t forget to write default. Here we recommend using Object or Map as conditional storage.

const actions = {
  1: 'processing',
  2: 'fail',
  3: 'success',
  4: 'cancel',
  default: 'other',
};

console.log(actions[status] ?? actions.default);

Map is more powerful. The key of an object can only be a string or a symbol, but the key of a Map can be an object or more, which can be used as a conditional joint judgment.
const actions = new Map([

  [/^sign_[1-3]$/, () => 'A'],
  [/^sign_5$/, () => 'B'],
  //...
]);

const action = [...actions].filter(([key, value]) => key.test(`sign_${status}`));
action.forEach(([key, value]) => value());

Make good use of expressions

Make good use of expressions and avoid spaghetti code. Simple conditional judgments can be replaced with ternary operators. Ordinary for loops can be replaced by map and forEach.

reduce complexity

The more lines of code a logic has, the more difficult it is to maintain. At this time, we need to extract the relevant logic into another function to reduce the complexity of the context. Here we suggest that the code size of a function should not exceed one screen at a width of 120 characters.
It is worth noting that the number of formal parameters defined by function is best controlled within 3, otherwise it is easy to neglect the order of passing in, thus making it difficult to maintain. If there are too many parameters, related parameters need to be aggregated into objects and passed.

remove duplicate code

Duplicate code is number one in Bad Smell, so do your best to avoid it. Because it means that when you need to modify some logic, there will be multiple places that need to be modified.
order of introduction

In import, we agree to put the packages in node_modules first, and then the packages with relative paths. Sometimes the different import order of a css will lead to different execution priority.

Use declarative

Declarative programming: Tell the "machine" what you want (what), and let the machine figure out how to do it (how). Imperative programming: Command the "machine" how to do things (how), so that no matter what you want (what), it will be implemented according to your order. The world is wonderful, stay away from imperatives and save time to experience life.

// Declarative: filter the results I need
const result = dataSource.filter((dataItem) => dataItem.age > 10);

// 命令式:亲力而为查找/追加数据
let result = [];`在这里插入代码片`
dataSource.forEach((dataItem) => {
  if (dataItem.age > 10) {
    result.push(dataItem);
  }
});

At this time, some people will say that imperative programming has good performance. In fact, we don't need to do premature optimization when writing code, and that little performance loss can be regarded as a drop in the bucket compared with maintainability.

write business notes

Excellent code naming does not require comments, code is comments, and comments will be redundant. At this time, the logic of a certain business is inseparable from accurate annotations, which can help us better understand the detailed logic of the business. What needs to be required is that the code change comments should also be updated accordingly.

functional programming

Functional programming is getting more and more attention, including react follows this philosophy.

Functions are "first class citizens"

A variable can be a function and can be used as an argument of another function

function increaseOperator(user) {
  return user.age + 1;
}

userList.filter(Boolean).map(increaseOperator);

pure function

That is, the same input will always get the same output, and there will be no observable side effects. If you use setTimeout, Promise or more operations with unexpected conditions happen. Then this kind of operation is called "side effect" Effect.
Each function can be viewed as an independent unit. The benefits of pure functions: easy composition, cacheable, testable, referentially transparent, easy to concurrency, etc.
Like slice and splice, slice meets the definition of a pure function because it is guaranteed to return the same output for the same input. Instead, splice mutates the array on which it is called, which has the observable side effect that the original array is permanently changed.

var countList = [1, 2, 3, 4, 5];

// 纯的
countList.slice(0, 3);
//=> [1, 2, 3]

countList.slice(0, 3);
//=> [1, 2, 3]

// 不纯的
countList.splice(0, 3);
//=> [1, 2, 3]

countList.splice(0, 3);
//=> [4, 5]

Immutable data
Each operation does not modify the original value, but returns a new value, which corresponds to no side effects. The immutable data model is easy to debug without worrying about the current data being changed elsewhere.

Well-established TS type

Typescript has a powerful type system, which makes up for javascript's shortcomings in types. What we need to pay attention to when writing typescript code is not to use implicit/explicit any type. If there is an uncertain type, the first thing to consider is generics to constrain it, followed by unknown to add assertions, and finally any.

// 典型类型完备的函数
function pick<T, K extends keyof T>(obj: T, keys: K[]) {
  return Object.fromEntries(keys.map((key) => [key, obj[key]])) as Pick<T, K>;
}

pick(userInfo, ['email', 'name']);

Guess you like

Origin blog.csdn.net/weixin_45361998/article/details/121261085