JS代码其实可以这样写

日常工作中,我确实经常去帮大家review代码,长期以来,我发现有些个功能函数,JS其实可以稍微调整一下,或者换个方式来处理,代码就会看起来更清晰,更简洁,甚至效率更高,主要是还更好理解。 下面我列举有5个案例,我们一起来看一下

一、建议考虑使用FlatMap方法

先来看一段同时使用filtermap方法遍历数组的代码。我相信这种场景大家一定碰到过。为了说明问题,这里我用简单的数字内容来举个例子。

js 复制代码
const squaredOddNumbers = numbers
    .filter(num => num % 2 !== 0)
    .map(num => num * num)

console.log(squaredOddNumbers);
// 输出:[1, 9, 25, 49, 81]

上面代码这样写,没什么问题,而且方法的连用也是比较推荐的处理方式, 但是,还是请多想想,其实我们有更好的方式来处理这一类问题。

现在我们看使用FlatMap如何实现的

js 复制代码
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const squaredOddNumbers = numbers.flatMap(num => 
    num % 2 !== 0 ? [num * num] : []
);

console.log(squaredOddNumbers);
// 输出:[1, 9, 25, 49, 81]

使用FlatMap的好处是

只要遍历一遍,而且不产生中间多余数组

二、建议调整数组方法调用的顺序

日常工作中写的比较多的数组方法有filter()find()map()reduce(),在必要的场景下,我们也建议将这些个方法连起来一起调用。但是,一定要注意调用顺序,否则也会影响效率问题。 比如下面这样:

js 复制代码
const numbers = [9, 3, 6, 4, 8, 1, 2, 5, 7];
numbers
  .sort((a, b) => a - b)
  .filter((n) => n % 2 !== 0)
  .map((n) => n ** 3);

仔细看上面这段代码,你就会发现

如果我们首先使用过滤器,然后在排序,这样执行就能提高效率

js 复制代码
numbers
  .filter((n) => n % 2 !== 0)
  .sort((a, b) => a - b)
  .map((n) => n ** 3);

三、建议这里使用reduce方法

你写的代码一定要让大家看的懂,代码要简洁,然而,有些方法它就出于这个目的创造的,如果你又不用,那就太可惜了,比如reduce方法。 举个例子,我们先从接口中拉出一段数据,然后对数据内容进行分类处理,像下面代码这样

js 复制代码
fetch("https://jsonplaceholder.typicode.com/todos/")
  .then(res=>res.json())
  .then(todos=>{

    // using Map
    const todosForUserMap = {};
    todos.forEach(todo=>{
      if (todosForUserMap[todo.userId]){
        todosForUserMap[todo.userId].push(todo);  
      }else{
        todosForUserMap[todo.userId] = [todo];
      }  
    })

    console.log(todosForUserMap)
  })

我看到大多数前端开发人员都会使用forEach方法或者错误的使用map方法去处理,相比之下,实际上这里特别适合使用reduce方法

看起来会更清晰而且更容易理解

js 复制代码
fetch("https://jsonplaceholder.typicode.com/todos/")
  .then(res=>res.json())
  .then(todos=>{
  
    // using Map
    const todosForUserMap = todos.reduce((accumulator, todo)=>{
      if (accumulator[todo.userId]) accumulator[todo.userId].push(todo);
      if (!accumulator[todo.userId]) accumulator[todo.userId] = [todo];
      return accumulator;
    },{})

    console.log(todosForUserMap)
  })

四、建议使用原生JavaScript类

上面这张很清晰明了的拆解了URL的每一部分

关于页面的URL我们可以组装也可以拆卸,这里说一下URL各部分的组装问题,你现在或者曾经肯定处理过URL拼接的问题,代码可能是这么写的

js 复制代码
function getUrl(param){
  const { category, limit, userId } = param;
  const baseURL = "https://fakestoreapi.com/products";
  const limtParams = limit ? `limit=${Number(limit)}` : '';
  const userIdParams = limit ? `userId=${Number(userId)}` : '';
  return `${baseURL}${category ? `/category/${category}?` : ""}${limtParams}&${userIdParams}`;    
}

这样写虽然能够实现,但是代码看起来很混乱,很可能会被破坏,并且每次都需要你在最后添加一些规则,添加一些其他参数。 比如,你可能忘记添加/或者&符号就会导致错误,下面看看原生类怎么实现的,可以对比一下两者区别

js 复制代码
function constructURL(param) {
  const { category, limit, userId } = param;
  const baseURL = "https://fakestoreapi.com/products";
  const url = new URL(baseURL);
  const params = new URLSearchParams();

  if (category) url.pathname += `/category/${category}`;
  if (limit) params.append('limit', Number(limit).toString());
  if (userId) params.append('userId', Number(userId).toString());

  url.search = params.toString();
  return url.toString();
}

这样看来,在处理URL组装问题上是不是可以考虑使用原生类了?

五、建议使用生成器

提到生成器,大家可能只是听过,或者知道怎么使用,而实际项目中很少去用。实际上它有很多使用场景。 使用生成器能够节省很多代码,代码也非常清晰。如,进行异步操作或者按需循环或者按需加载时。

看这段代码:

js 复制代码
async function *fetchProducts(){
  while (true){
    const productUrl = "https://fakestoreapi.com/products?limit=2";
    const res = await fetch(productUrl)
    const data = await res.json()
    yield data;
  }
}

async function main() {
  const itr = fetchProducts();
  console.log( await itr.next() );
}

上面代码中main函数,可以根据用户交互或者其它技巧来调用。因为这里不希望无限加载。

总结

好了,就说这几点,日常工作中,希望大家都写出高质量的代码。

相关推荐
J总裁的小芒果5 分钟前
Vue3 el-table 默认选中 传入的数组
前端·javascript·elementui·typescript
Lei_zhen967 分钟前
记录一次electron-builder报错ENOENT: no such file or directory, rename xxxx的问题
前端·javascript·electron
辣条小哥哥9 分钟前
electron主进程和渲染进程之间的通信
javascript·electron·ecmascript
咖喱鱼蛋9 分钟前
Electron一些概念理解
前端·javascript·electron
yqcoder11 分钟前
Vue3 + Vite + Electron + TS 项目构建
前端·javascript·vue.js
鑫宝Code28 分钟前
【React】React Router:深入理解前端路由的工作原理
前端·react.js·前端框架
Mr_Xuhhh2 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
永乐春秋3 小时前
WEB攻防-通用漏洞&文件上传&js验证&mime&user.ini&语言特性
前端
鸽鸽程序猿3 小时前
【前端】CSS
前端·css
ggdpzhk3 小时前
VUE:基于MVVN的前端js框架
前端·javascript·vue.js