文章继续更新中…,欢迎保藏。感兴趣的能够去访问dev社区 dev.to

洁净和可保护的代码关于任何软件项目的长期成功和可扩展性都是至关重要的。它改进了团队成员之间的协作,削减了bug的可能性,并使代码更易于了解、测试和保护。在这篇文章中,咱们将探索一些用JavaScript编写洁净且可保护的代码的最佳实践,经过供给代码示例来阐明每种实践。

共同的代码格局

共同的代码格局关于可读性至关重要。它能够协助开发人员更快地了解代码并改进协作。运用共同且广泛承受的代码款式指南(如ESLint供给的指南),并装备编辑器或IDE以相应地主动设置代码格局。示例:

// Bad practice
function calculateSum(a,b){
    return a + b;
}
// Good practice
function calculateSum(a, b) {
  return a + b;
}

有含义的变量和函数称号

为变量、函数和类运用描述性的、有含义的称号。避免运用单字母变量名或缩写,以免混杂别人。这种做法增强了代码的可读性,并削减了对注释的需求。
JavaScript中,标准是对变量和函数运用camel-case(如myVariableName),对类运用Pascal case(如MyClassName)。
示例:

// Bad practice
const x = 5;
// Good practice
const numberOfStudents = 5;

抛弃运用魔法数字和魔法字符串

魔术数字和魔术字符串在JavaScript中很常见,由于其没有清晰的含义,不推荐运用。牺牲了可读性,可保护性,并且可能形成潜在的过错。

// Bad practice
function getErrorMessage(code) {
  switch (code) {
    case "ERR001":
      return "连接失利"; // "ERR001" 魔法字符串
    case "ERR002":
      return "无权限"; // "ERR002" 魔法字符串
    default:
      return "不知道过错";
  }
}
// Good practice
const errCode = {
   connectErr: "ERR001",
   authError: "ERR002"
}
function getErrorMessage(code) {
  switch (code) {
    case errCode.connectErr:
      return "连接失利"; // "ERR001" 魔法字符串
    case errCode.authError:
      return "无权限"; // "ERR002" 魔法字符串
    default:
      return "不知道过错";
  }
}

模块化和单一责任准则

遵循函数和类的单一责任准则。每个函数或类都应该有一个清晰界说的单一责任。这种办法进步了代码的可重用性,并使测试、调试和保护更容易。
示例:

// Bad practice
function calculateSumAndAverage(numbers) {
  let sum = 0;
  for (let i = 0; i < numbers.length; i++) {
    sum += numbers[i];
  }
  const average = sum / numbers.length;
  return [sum, average];
}
// Good practice
function calculateSum(numbers) {
  let sum = 0;
  for (let i = 0; i < numbers.length; i++) {
    sum += numbers[i];
  }
  return sum;
}
function calculateAverage(numbers) {
  const sum = calculateSum(numbers);
  const average = sum / numbers.length;
  return average;
}

避免运用全局变量

尽量削减全局变量的运用,由于它们会导致命名抵触,并使代码更难推理。相反,将代码封装在函数或模块中,并尽可能运用局部变量。
示例:

// Bad practice
let count = 0;
function incrementCount() {
  count++;
}
// Good practice
function createCounter() {
  let count = 0;
  function incrementCount() {
    count++;
  }
  return {
    incrementCount,
    getCount() {
      return count;
    }
  };
}
const counter = createCounter();
counter.incrementCount();

避免代码重复

重复的代码不只会导致代码臃肿,并且会使保护和过错修正更具挑战性。将可重用代码封装到函数或类中,并努力选用DRY(Don’t Repeat Yourself不要重复自己)办法。假如您发现自己在复制和粘贴代码,请考虑将其重构为可重用的函数或模块。
示例:

// Bad practice
function calculateAreaOfRectangle(length, width) {
  return length * width;
}
function calculatePerimeterOfRectangle(length, width) {
  return 2 * (length + width);
}
// Good practice
function calculateArea(length, width) {
  return length * width;
}
function calculatePerimeter(length, width) {
  return 2 * (length + width);
}

准确地运用注释

尽管洁净的代码应该是自解说的,但在某些状况下,需求注释来供给额定的上下文或弄清杂乱的逻辑。有控制地运用注释,使它们简练而有含义。专注于解说“WHY”而不是“HOW“
示例

// Bad practice
function calculateTotalPrice(products) {
  // 遍历产品
  let totalPrice = 0;
  for (let i = 0; i < products.length; i++) {
    totalPrice += products[i].price;
  }
  return totalPrice;
}
// Good practice
function calculateTotalPrice(products) {
  let totalPrice = 0;
  for (let i = 0; i < products.length; i++) {
    totalPrice += products[i].price;
  }
  return totalPrice;
  // 总价格是经过对数组中所有产品的价格求和来核算的
}

优化功用

高效的代码能够进步应用程序的整体功用。留意不必要的核算、过多的内存运用和潜在的瓶颈。运用恰当的数据结构和算法来优化功用。运用Chrome DevTools等东西分析和测量您的代码,以识别功用问题并相应地处理它们。
示例:有序数组查找

// 有序数组查找
// Bad practice
function findItemIndex(array, target) {
  for (let i = 0; i < array.length; i++) {
    if (array[i] === target) {
      return i;
    }
  }
  return -1;
}
// Good practice 运用二分法
function findItemIndex(array, target) {
  let left = 0;
  let right = array.length - 1;
  while (left <= right) {
    const mid = Math.floor((left + right) / 2);
    if (array[mid] === target) {
      return mid;
    }
    if (array[mid] < target) {
      left = mid + 1;
    } else {
      right = mid - 1;
    }
  }
  return -1;
}

编写单元测试

单元测试关于保证代码的正确性和可保护性至关重要。编写主动化测试以掩盖不同的场景和边缘状况。这有助于及早捕获过错,促进代码重构,在修正代码时也更有决心。运用Jest或Mocha等测试结构来编写和运行测试。
示例(运用Jest):

// Code
function sum(a, b) {
  return a + b;
}
// Test
test('sum function adds two numbers correctly', () => {
  expect(sum(2, 3)).toBe(5);
  expect(sum(-1, 5)).toBe(4);
  expect(sum(0, 0)).toBe(0);
});

运用函数式编程概念

函数式编程概念,如不变性和纯函数,能够使代码更可猜测,更容易推理。运用不可变的数据结构,尽可能避免改动目标或数组。编写没有副作用的纯函数,并为相同的输入生成相同的输出,使其更易于测试和调试。
示例:

// Bad practice
let total = 0;
function addToTotal(value) {
  total += value;
}
// Good practice
function addToTotal(total, value) {
  return total + value;
}

慎重修正函数参数

直接修正目标的特点或作为函数参数传递的数组的值可能会导致不良的副作用和难以跟踪的过错。相反,请考虑回来一个新目标或数组。这种实践与函数式编程的准则非常共同,其间不变性是要害。

// ❌ 修正参数
function updateName (user) {
  user.name = 'bob'
}
let user = { name: 'alice' }
updateName(user)
console.log(user) // { name: 'bob' }
// ✅ 避免改动函数参数,而是回来新目标
function updateName (user) {
  return { ...user, name: 'bob' }
}
let user = { name: 'alice' }
let updatedUser = updateName(user)
console.log(user) // { name: 'alice' }
console.log(updatedUser) // { name: 'bob' }

运用JSDoc记录代码

运用JSDoc为函数、类和模块编写文档。这有助于其他开发人员了解您的代码,并使其更易于保护。

/**
 * 两数求和.
 * @param {number} a - 榜首个数.
 * @param {number} b - 第二个数.
 * @returns {number} 两数之和.
 */
function add(a, b) {
  return a + b;
}

运用 ESLint 和 Prettier等东西

// .eslintrc.json
{
  "extends": ["eslint:recommended", "prettier"],
  "plugins": ["prettier"],
  "rules": {
    "prettier/prettier": "error"
  }
}

遵循 SoC(关注点分离)准则

为了保持简单和有组织,最好不要运用JavaScript来增加直接款式。这便是所谓的关注点分离(SoC)。相反,运用classListAPI增加和删去类,并在CSS中界说款式。经过这种方法,CSS完结所有款式,JavaScript处理应用程序的所有其他功用。
这种编程概念并不局限于JavaScript,(SoC)关注点分离是一种分离功用而不是混杂不同技术的实践。

// ❌ 避免运用 JavaScript 进行款式处理
let element = document.getElementById('my-element')
element.style.color = 'red'
// ✅ 经过 增加/删去 类更改款式
let element = document.getElementById('my-element')
element.classList.add('my-class')

运用for...of而不是for循环

ECMAScript 6中引入的for...of语句是传统for循环的更有效的替代计划。它带有一个内置的迭代器,消除了界说变量和长度值的需求。这会使你的代码更洁净。
留意:for of 不能用来遍历目标,由于它没有部署 Symbol.iterator 特点。

JavaScript中的类不会被进步

与函数不同,JavaScript中的类不会被进步,这意味着你需求在调用一个类之前声明它。这可能看起来违反直觉,特别是假如你习惯了函数进步,但这是一个基本准则,在JavaScript中运用类时必须了解和尊重。

// ❌ 在声明之前调用类:
const hat = new Hat('Red', 1000)
hat.show()
class Hat {
  constructor (color, price) {
    this.color = color
    this.price = price
  }
  show () {
    console.log(`This ${this.color} hat costs $${this.price}`)
  }
}
// ✅ 在声明之后调用:
class Hat {
  constructor (color, price) {
    this.color = color
    this.price = price
  }
  show () {
    console.log(`This ${this.color} hat costs $${this.price}`)
  }
}
const hat = new Hat('Red', 1000)

Promises 反常处理

在JavaScript的异步场景中,promise是一个流行的概念。但是,必须正确处理它们以避免意外行为。JavaScript供给了一个try...catch块,可用于处理在履行异步代码期间可能出现的反常。经过这种方法,您能够保证过错被捕获并得到恰当的处理,从而保持代码的健壮性。

// ❌ 未处理promise反常
async function fetchData () {
  const response = await fetch('xxx')
  const data = await response.json()
  return data
}
// ✅ 处理promise反常
async function fetchData () {
  try {
    const response = await fetch('xxx')
    const data = await response.json()
    return data
  } catch (error) {
    // 在这里处理反常
    throw new Error(error)
  }
}

避免代码中过度嵌套

能够运用卫语句来处理这种问题

// ❌ 嵌套代码块太多,不运用return要害字
function checkNumber (num) {
  if (num > 0) {
    console.log('Number is positive.')
  } else {
    if (num < 0) {
      console.log('Number is negative.')
    } else {
      console.log('Number is zero.')
    }
  }
}
// ✅ 运用return要害字而不是else语句
function checkNumber (num) {
  if (num > 0) {
    console.log('Number is positive.')
    return
  }
  if (num < 0) {
    console.log('Number is negative.')
    return
  }
  console.log('Number is zero.')
}

总结:

编写洁净和可保护的代码不只仅是个人喜爱的问题;这是职业责任。经过遵循本文中概述的最佳实践,您能够进步JavaScript代码的质量,使其更易于了解,保护和协作,并保证软件项目的长期成功。共同性、可读性、模块化和过错处理是在努力获得洁净和可保护的代码时要牢记的要害准则。快乐编码!