zoukankan      html  css  js  c++  java
  • 4个错误使用JavaScript数组方法的案例

    译者按: 做一个有追求的工程师,代码不是随便写的!

    为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。

    小编推荐:Fundebug专注于JavaScript、微信小程序、微信小游戏,Node.js和Java线上bug实时监控。真的是一个很好用的bug监控服务,众多大佬公司都在使用。

    我保证这是一篇可以快速阅读并吸收的文章。在过去的几个月里,我检查的所有的pull request中,都犯了这4个的错误。我写这篇文章的另一个原因在于我自己也犯过这些错。我们来看看如何正确地使用它们!

    1. 不要使用Array.indexOf,使用Array.includes

    “如果你要在数组中查找元素,使用Array.indexOf!”。记得在我学习JavaScript课程时候,有这样一句话。这句话没错,确实可以这么使用!

    根据MDN文档:“Array.indexOf会返回被查找元素第一个匹配的位置的下标。”因此,如果后面需要用到这个索引,Array.indexOf是一个很好的解法。

    但是,我们要解决的问题是:查找数组中是否包含某个元素。这是一个Yes/No的问题,是一个返回布尔类型的真假问题。因此,我建议使用Array.includes,它会返回一个布尔值。

    'use strict';
    
    const characters = [
      'ironman',
      'black_widow',
      'hulk',
      'captain_america',
      'hulk',
      'thor',
    ];
    
    console.log(characters.indexOf('hulk'));
    // 2
    console.log(characters.indexOf('batman'));
    // -1
    
    console.log(characters.includes('hulk'));
    // true
    console.log(characters.includes('batman'));
    // false
    

    2. 不要使用Array.filter,使用Array.find

    Array.filter是一个很有用的函数,它返回一个满足过滤条件的新数组。正如其名字表达的含义,它是用来做过滤的。

    但是,如果我们知道我们要的结果只有一个元素的时候,我就不建议使用它了。比如,如果我们的回调函数定义用一个唯一的ID来过滤,那么结果必然唯一了。在这个情况下,Array.filter会返回只有一个元素的数组。因为既然能通过一个特定的ID来查找,我们已经确定只有一个元素了,那么使用数组就没有意义。

    另外,我们再来聊聊性能问题。为了返回所有匹配的元素,Array.filter需要查找整个数组。可以想象一下,如果有上百个元素满足过滤条件,那么返回的数组就很大。

    为了避免这样的情况,我建议使用Array.find。它仅仅返回第一个满足过滤条件的元素。而且,Array.find会在查找到第一个满足条件的元素后就结束执行,而不会查找整个数组。

    'use strict';
    
    const characters = [
      { id: 1, name: 'ironman' },
      { id: 2, name: 'black_widow' },
      { id: 3, name: 'captain_america' },
      { id: 4, name: 'captain_america' },
    ];
    
    function getCharacter(name) {
      return character => character.name === name;
    }
    
    console.log(characters.filter(getCharacter('captain_america')));
    // [
    //   { id: 3, name: 'captain_america' },
    //   { id: 4, name: 'captain_america' },
    // ]
    
    console.log(characters.find(getCharacter('captain_america')));
    // { id: 3, name: 'captain_america' }
    

    3. 不要使用Array.find,使用Array.some

    我承认我犯过很多次错误。后来,一个很要好的朋友让我去看看MDN的文档,说有更好的解决方案。这个情况和刚刚提到的Array.indexOf/Array.includes很像。

    在前面的例子中,我们看到Array.find接受一个过滤函数,返回满足的元素。那么,如果我们要查找一个数组是否包含某个元素的时候,Array.find是否是最佳的方案呢?可能不是,因为它返回的是元素具体的值,而不是布尔值。

    我推荐大家使用Array.some,它会返回布尔值。

    'use strict';
    
    const characters = [
      { id: 1, name: 'ironman', env: 'marvel' },
      { id: 2, name: 'black_widow', env: 'marvel' },
      { id: 3, name: 'wonder_woman', env: 'dc_comics' },
    ];
    
    function hasCharacterFrom(env) {
      return character => character.env === env;
    }
    
    console.log(characters.find(hasCharacterFrom('marvel')));
    // { id: 1, name: 'ironman', env: 'marvel' }
    
    console.log(characters.some(hasCharacterFrom('marvel')));
    // true
    

    4. 不要使用Array.map和Array.filter组合,使用Array.reduce

    Array.reduce有点难以理解!但是,如果我们每次在同时使用Array.filter和Array.map的时候,你是否觉察到需要点东西,对不?

    我的意思是:我们对整个数组循环了2遍。第一次是过滤返回一个新的数组,第二次通过map又构造一个新的数组。我们使用了两个数组方法,每一个方法都有各自的回调函数,而且Array.filter返回的数组以后再也不会用到。

    为了避免低效率,我建议使用Array.reduce。同样的结果,更优雅的代码!请看下面的例子:

    'use strict';
    
    const characters = [
      { name: 'ironman', env: 'marvel' },
      { name: 'black_widow', env: 'marvel' },
      { name: 'wonder_woman', env: 'dc_comics' },
    ];
    
    console.log(
      characters
        .filter(character => character.env === 'marvel')
        .map(character => Object.assign({}, character, { alsoSeenIn: ['Avengers'] }))
    );
    // [
    //   { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] },
    //   { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] }
    // ]
    
    console.log(
      characters
        .reduce((acc, character) => {
          return character.env === 'marvel'
            ? acc.concat(Object.assign({}, character, { alsoSeenIn: ['Avengers'] }))
            : acc;
        }, [])
    )
    // [
    //   { name: 'ironman', env: 'marvel', alsoSeenIn: ['Avengers'] },
    //   { name: 'black_widow', env: 'marvel', alsoSeenIn: ['Avengers'] }
    // ]
    

    备注

    malgosiastp and David Piepgrass在评论中提到:在使用Array.find和Array.includes前请注意检查兼容性,因为最新的IE不支持。

    关于Fundebug

    Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了6亿+错误事件,得到了Google、360、金山软件等众多知名用户的认可。欢迎免费试用!

    版权声明:
    转载时请注明作者Fundebug以及本文地址:
    https://blog.fundebug.com/2018/09/06/make-better-use-of-arrays/

  • 相关阅读:
    CRM安装过程问题总结
    SQL Server Active Directory Helper 无法启动
    CRM导出Excel记录的最大数量
    CRM名词解释
    CRM根据不同的角色过滤视图
    asp.net C# webservice安全性方案
    利用MSCRM4.0 Trace功能跟踪详细错误信息
    事件1058处理过程,处理组策略失败.
    在 Windows Server 2003 中配置网络负载平衡
    对比SQL中简单嵌套查询与非嵌套查询的异同
  • 原文地址:https://www.cnblogs.com/fundebug/p/make_better_use_of_arrays.html
Copyright © 2011-2022 走看看