qdkfweb.cn

JS代码其实可以这样写

本文作者从减少不必要的操作、使用更高效的算法和减少内存占用三个方面来介绍了 JavaScript 代码优化的技巧。作者还举了一些具体的例子来说明这些技巧的使用。

这篇文章适合所有 JavaScript 开发者阅读,尤其是希望提高代码性能和效率的开发者。以下为正文:

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

一、建议考虑使用FlatMap方法

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

const squaredOddNumbers = numbers
 .filter(num => num % 2 !== 0)
 .map(num => num * num)
console.log(squaredOddNumbers);
// 输出:[1, 9, 25, 49, 81]

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

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(),在必要的场景下,我们也建议将这些个方法连起来一起调用。但是,一定要注意调用顺序,否则也会影响效率问题。比如下面这样:

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);

仔细看上面这段代码,你就会发现如果我们首先使用过滤器,然后在排序,这样执行就能提高效率

 .filter((n) => n % 2 !== 0)
 .sort((a, b) => a - b)
 .map((n) => n ** 3);

三、建议这里使用reduce方法

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

 .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方法看起来会更清晰而且更容易理解

 .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拼接的问题,代码可能是这么写的

 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}`; 
}

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

 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组装问题上是不是可以考虑使用原生类了?

五、建议使用生成器

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

 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函数,可以根据用户交互或者其它技巧来调用。因为这里不希望无限加载。

总结

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

作者:公号是前端必修课
https://juejin.cn/post/7300151966964613132

关注我

如果喜欢我的分享,点击下方关注,文末点一个赞 👍 ➕分享 是对我最大的支持

我的微信公众号:前端开发博客,在后台回复以下关键字可以获取资源。

  • 回复「小抄」,领取Vue、JavaScript 和 WebComponent 小抄 PDF

  • 回复「Vue脑图」获取 Vue 相关脑图

  • 回复「思维图」获取 JavaScript 相关思维图

  • 回复「简历」获取简历制作建议

  • 回复「简历模板」获取精选的简历模板

  • 回复「加群」进入500人前端精英群

  • 回复「电子书」下载我整理的大量前端资源,含面试、Vue实战项目、CSS和JavaScript电子书等。

  • 回复「知识点」下载高清JavaScript知识点图谱

posted @ 2023-11-16 22:02  前端博客  阅读(5)  评论(0编辑  收藏  举报
qdkfweb.cn