你用过这些JavaScript技巧和实践吗

本文翻译自 I Bet You Don't Use These JavaScript Tricks and Practices,作者:Nirjal Paudel, 略有删改。

本文推荐一些实际开发中的JavaScript技巧和实践,希望能对你有所帮助,有兴趣的可以看看原文。

1.使用FlatMap

JavaScript中的Flat Map是一个很好用的方法。Flat Map实质上是将映射技术和过滤数组技术结合在了一起。更建议你使用flatMap()而不是filter()map()的组合。

FlatMap只执行一次,不会生成中间数组,但是filter()map()的组合会生成一个中间数组。

js 复制代码
// using filterAndMap
console.time("filterAndMap")
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const squaredOddNumbers = numbers
    .filter(num => num % 2 !== 0)
    .map(num => num * num)

console.log(squaredOddNumbers); // [1, 9, 25, 49, 81]
console.timeEnd("filterAndMap")

以下是打印代码运行的执行时间:

js 复制代码
console.time("filterAndMap")
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]
console.timeEnd("filterAndMap")

以下是打印代码运行的执行时间:

通过两者运行的时间即可很容易的看出差距。

2. 数组排序

数组方法是一些帮助我们与数组进行交互的最重要的方法之一。在 JavaScript 中有许多数组方法可用。最常用的数组方法包括 .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 复制代码
const numbers = [9, 3, 6, 4, 8, 1, 2, 5, 7];

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

3.不经常使用的 reduce 函数

我见过很多前端开发者在处理这个问题时遇到困难。比如像react-charts这样的包要求以对象结构传递数据,但实际上react-charts的实现要求以键分组的格式传递数据,所以我见过大多数开发者使用.forEach()方法或错误地使用map()方法来处理这个问题,就像下面这样:

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方法。map方法在这里明显不适用,因为它会在幕后会为每个元素创建一个数组。假设数组有1000个条目,那么在map中将创建一个1000个条目的空数组,而在forEach中不会创建这样的数组。

但我们不使用上面的两种方法,一个相当简洁和易读的方法是使用数组的 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)
  })

这样不会创建任何不必要的数组,代码更干净且更好用。它与forEach()类似,但建议用下面的方式,因为它更清晰,更容易理解。

4.未充分使用原生JavaScript类

JavaScript自带很多原生javascript类,可以帮助你很容易地创建/实例化URL,Header等。以下代码可能比较常见,有人会试图像这样在URL中处理参数。

js 复制代码
async function getUrl(userId, limit, category){
  return `https://fakestoreapi.com/products${category ? `/category/${category}` : ""}${limit ? Number(limit):""}${userId? Number(userId):""}`;    
}

上面的代码看着很混乱,很可能会中断,每次都需要你在最后添加一些规则,添加一些其他参数,通过使用本地类,如URL,我们可以改进更好的代码。改进的代码看起来像下面这样。

js 复制代码
function constructURL(category, limit, userId) {
  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构建条件。这里的URL对象遵循建造者模式(BuilderPattern),它是你可以在代码中实现的许多设计模式之一,可以将复杂的逻辑放在一个单独的地方处理,同时也提高了代码可读性。

最后

这些JavaScript技巧和实践旨在提高开发效率、增强代码质量和性能优化。希望对你有用且能从中获得一些启发,并应用到实际项目中。


看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~

专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)

相关推荐
weifont1 小时前
聊一聊Electron中Chromium多进程架构
javascript·架构·electron
大得3691 小时前
electron结合vue,直接访问静态文件如何跳转访问路径
javascript·vue.js·electron
水银嘻嘻3 小时前
12 web 自动化之基于关键字+数据驱动-反射自动化框架搭建
运维·前端·自动化
it_remember3 小时前
新建一个reactnative 0.72.0的项目
javascript·react native·react.js
小嘟嚷ovo3 小时前
h5,原生html,echarts关系网实现
前端·html·echarts
十一吖i4 小时前
Vue3项目使用ElDrawer后select方法不生效
前端
只可远观4 小时前
Flutter目录结构介绍、入口、Widget、Center组件、Text组件、MaterialApp组件、Scaffold组件
前端·flutter
周胡杰4 小时前
组件导航 (HMRouter)+flutter项目搭建-混合开发+分栏效果
前端·flutter·华为·harmonyos·鸿蒙·鸿蒙系统
不念霉运4 小时前
Gitee DevOps:中国企业数字化转型的“本土化加速器“
运维·gitee·团队开发·代码规范·devops·代码复审
敲代码的小吉米4 小时前
前端上传el-upload、原生input本地文件pdf格式(纯前端预览本地文件不走后端接口)
前端·javascript·pdf·状态模式