JavaScript 几个实用技巧

1. 使用 FlatMap

在 JavaScript 中,Flat Map 是一种很棒的技术,你可以在这里了解。FlatMap 本质上将 map 和 filter 数组方法的技术结合成了一种。我建议你使用 flatMap() 而不是 filter() 和 map() 的组合。

FlatMap 只需单次遍历,并且不会产生中间数组,而 filter() 和 map() 的组合会产生中间数组。

// 使用 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")
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()。它们可以合并在一起产生一些很棒的模式,就像这样

// 一个仅对数组进行排序的数组方法  
// 仅适用于奇数,并将其提高到3的幂次方  
numbers  
  .sort((a, b) => a - b)  
  .filter((n) => n % 2 !== 0)  
  .map((n) => n ** 3);

乍一看,上面的程序看起来很好,对吧,但是这里有一个大问题。注意我们是如何首先对数字进行排序,然后再进行过滤的。如果我们先使用 filter 再进行排序和提高幂次方,我们可以做更少的任务。这样,我们可以优化一组由(.)链接的数组方法。

上面的最佳代码为

const numbers = [9, 3, 6, 4, 8, 1, 2, 5, 7];  
  
// 一个仅对数组进行排序的数组方法  
// 仅适用于奇数,并将其提高到3的幂次方  
numbers  
  .filter((n) => n % 2 !== 0)  
  .sort((a, b) => a - b)  
  .map((n) => n ** 3);

3. 使用 reduce。

我发现很多前端开发者都有这个问题。例如,像 react-charts 这样的包要求以对象结构提供数据,但是 react-charts 的实现要求以按键分组的格式提供数据,因此我看到大多数开发者使用 .forEach() 方法或不正确地使用 map() 方法,就像这样

fetch("https://jsonplaceholder.typicode.com/todos/")  
  .then(res=>res.json())  
  .then(todos=>{  
      
    // 使用 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个条目,那么将会为每个元素创建一个包含1000个条目的空数组,这个数组创建不会在 forEach() 中发生。

与上述任何方法都不同,一个更干净、更可读的方法是使用 Array reduce 方法 ,上面的代码现在被更正为

fetch("https://jsonplaceholder.typicode.com/todos/")  
  .then(res=>res.json())  
  .then(todos=>{  
      
    // 使用 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 开发人员不常用的那些代码片段之一,它的知识仅限于编码面试。在数据获取的情况下,数据库/API 中的数据可能是无限的且量大,您将不得不在前端中流式传输它。在这种情况下,React 中最常用的解决方案是无限加载解决方案

你会如何在 nodejs 服务器或原生 JavaScript 中实现类似无限加载的功能?

这就是迭代器非常有用的地方。我们可以使用异步生成器之类的方式,而不是在请求中流式传输数据到本地存储或其他地方,以便稍后检索。这是使用异步生成器的一种方法。通过这种方式,

我们可以在 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;  
    // 在这里操作 UI,比如  
    // 或将其保存在 DB 或其他地方  
    // 将其用作副作用的地方  
    // 即使某些条件匹配,也会中断流  
  }  
}  
  
async function main() {  
  const itr = fetchProducts();  
  // 根据用户交互或其他技巧调用此函数,因为您不希望无限加载。  
  console.log( await itr.next() );  
}  
  
return main()

5. 使用原生 JavaScript 类。

JavaScript 自带原生 JavaScript 类,可以帮助您轻松创建/实例化诸如 URL、Headers 等东西。我们可能曾经看到有人试图像这样查询 URL 中的查询参数。

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

上面的代码混乱不堪,很可能会出错,每次需要添加一些规则时都需要在最后添加一些规则,使用像 URL 这样的原生类,我们可以改进我们的代码。改进后的代码如下。

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,这是您可以在代码中实现的许多设计模式之一,它将复杂逻辑隐藏在一个单独的地方,并提高了可读性。

  • 24
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值