• 04 Array Cardio ? 指南一
    • 实现效果
    • 炫酷的调试技巧
    • 过程指南
    • 相关知识
      • filter
      • map
      • sort
      • filter 和 map 的结合使用
      • reduce

    04 Array Cardio ? 指南一

    作者:©未枝丫
    简介:JavaScript30 是 Wes Bos 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。现在你看到的是这系列指南的第 4 篇。完整指南在 GitHub,喜欢请 Star 哦♪(^∇^*)

    实现效果

    这一部分主要是熟悉 Array 的几个基本方法,其中有两个(filter、map)是 ES5 定义的迭代方法,这些迭代方法都有一个特点,就是对数组的每一项都运行给定函数,根据使用的迭代方法的不同,有不同的返回结果。

    文档给出了一个初始操作的 inventor 数组,基于这个数组可以练习一下 Array 的各个方法,请打开 HTML 后在 Console 面板中查看输出结果。

    炫酷的调试技巧

    在 Console 中我们常用到的可能是 console.log() ,但它还有一个很炫的输出,按照表格来输出,效果如下:

    1. console.table(thing)

    console.table()

    过程指南

    1. 筛选 16 世纪出生的发明家
    2. 展示他们的姓和名
    3. 把他们按照年龄从大到小进行排序
    4. 计算所有的发明家加起来一共活了多少岁
    5. 按照他们活了多久来进行排序
    6. 筛选出一个网页里含有某个词语的标题
    7. 按照姓氏来对发明家进行排序
    8. 统计给出数组中各个物品的数量

    相关知识

    下面从简单的方法开始,后面有很多有意思的玩法。

    filter

    过滤操作,有点像 SQL 里面的 select 语句。筛出运行结果是 true 的组成数组返回。

    1. const __fifteen = inventors.filter(function(inventor) {
    2. if (inventor.year >= 1500 && inventor.year < 1600 ) {
    3. return true;
    4. } else {
    5. return false;
    6. }
    7. });
    8. console.table(__fifteen);

    前面几篇已经提到过箭头函数,这里可以简化一下,用箭头函数来写,而且由于 if 语句的存在并不是必要的,可以写成下面这样:

    1. const fifteen = inventors.filter(inventor =>(inventor.year >= 1500 && inventor.year < 1600));
    2. console.table(fifteen);

    map

    map 形象的理解就是,把数组中的每个元素进行处理后,返回一个新的数组。

    例子如下:

    1. // 展示数组对象 inventors 里发明家的姓名
    2. const fullNames = inventors.map(inventor => inventor.first + ' ' + inventor.last);

    sort

    默认情况下,Array.prototype.sort() 会将数组以字符串的形式进行升序排列(10 会排在 2 之前),但 sort 也可以接受一个函数作为参数。所以需要对数字大小排序时需要自己设定一个比较函数,例子如下:

    1. const __ordered = inventors.sort((a, b) => (a > b) ? 1 : -1);
    2. console.table(__ordered);

    filter 和 map 的结合使用

    这两个结合起来可以做一些有意思的事情,由于示范代码中用的页面是 Wikipedia,我重新找了个国内的页面,演示如下:

    筛选出这一个页面中包含 CSS 的书名。代码如下:

    1. // https://book.douban.com/tag/web
    2. const cate = document.querySelectorAll('.subject-list h2 a');
    3. const book = links
    4. .map(link => link.title)
    5. .filter(title => title.includes('CSS'));

    豆瓣书单

    除此之外,你还可以去自己个人订单的页面看一下今年买过的书,需要做的就是研究一下标签的 class 值或者是其他能够筛出来的标识信息,然后构造你自己的筛选语句。

    需要提一点,由 querySelectorAll() 获取到的是一个 NodeList ,它并非是 Array 类型的数据,所以并不具有 mapfilter 这样的方法,所以如果要进行筛选操作则需要把它转化成 Array 类型,使用下面示例之中的 Array.from() 来转化。

    1. var links = Array.from(document.querySelectorAll('#ordersContainer div.order div.a-row > a.a-link-normal'))
    2. var object = order.map( order => {
    3. var a = {};
    4. var time = order.querySelector('.order-info span.value').textContent.trim();
    5. var title = order.querySelector('div.a-row > a.a-link-normal').textContent.trim();
    6. a["time"] = time;
    7. return a;
    8. })

    Amazon 订单筛选

    reduce

    这是一个归并数组的方法,它接受一个函数作为参数(这个函数可以理解成累加器),它会遍历数组的所有项,然后构建一个最终的返回值,这个值就是这个累加器的第一个参数。例子如下:

    1. [0,1,2,3,4].reduce(function(previousValue, currentValue, index, array){
    2. return previousValue + currentValue;
    3. });

    而此处我们需要统计一个给定数组中各个项的值,恰好可以用到这个方法,在累加器之中,将统计信息存入一个新的对象,最后返回统计值。

    1. const data = ['car', 'car', 'truck', 'truck', 'bike', 'walk', 'car', 'van', 'bike', 'walk', 'car', 'van', 'car', 'truck' ];
    2. const reduce = data.reduce( (obj, item) => {
    3. if( !obj[item] ) {
    4. obj[item] = 0;
    5. }
    6. obj[item]++;
    7. return obj;
    8. }, {});
    9. console.log(reduce);