前端百题斩【019】——数组中方法原理早知道

写该系列文章的初衷是“让每位前端工程师掌握高频知识点,为工作助力”。这是前端百题斩的第19斩,希望朋友们关注公众号“执鸢者”,用知识武装自己的头脑。

js的Array对象可以调用很多方法,每一个方法都有其特殊的用途,但是很多情况下我们仅仅会使用这么高级方法,多于其实现过程知之甚少,本节就数组中的常用方法map、filter、reduce进行实现,帮助了解其原理。

19.1 map

img
19.1.1 基础

map() 方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。

  1. map方法的用法如下所示:

const new_array = arr.map(function callback(currentValue[, index[, array]]) {
 // ……
}[, thisArg])
  1. 小试牛刀

const arr = [1, 2, 3, 4];

const newArr = arr.map(value => value * 3);

console.log(arr); // [ 1, 2, 3, 4 ] 原数组不变
console.log(newArr); // [ 3, 6, 9, 12 ]
19.1.2 实现

map做的事情很单纯,就是处理每个元素然后返回一个新的数组,下面就来看看怎样实现自己的map函数。实现步骤如下所示:

  1. 判断输入的第一个参数是不是函数

  2. 获取需要处理的数组内容

  3. 新建一个新数组用于装载新的内容

  4. 对数组中每个值进行处理(注意改变this指向)

  5. 返回结果

Array.prototype.myMap = function(fn) {
    // 判断输入的第一个参数是不是函数
    if (typeof fn !== 'function') {
        throw new TypeError(fn + 'is not a function');
    }

    // 获取需要处理的数组内容
    const arr = this;
    const len = arr.length;
    // 新建一个空数组用于装载新的内容
    const temp = new Array(len);

    // 对数组中每个值进行处理
    for (let i = 0; i < len; i++) {
        // 获取第二个参数,改变this指向
        let result = fn.call(arguments[1], arr[i], i, arr);
        temp[i] = result;
    }
    // 返回新的结果
    return temp;
}

const arr = [1, 2, 3, 4];

const newArr = arr.myMap(value => value * 3);

console.log(arr); // [ 1, 2, 3, 4 ] 原数组不变
console.log(newArr); // [ 3, 6, 9, 12 ]

上述就是map的实现流程,并且经过验证与原生的map方法的结果一致。

19.2 filter

img
19.2.1 基础

filter() 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。

  1. filter方法的用法如下所示:

const newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
  1. 小试牛刀

const arr = [1, 2, 3, 4];

const newArr = arr.filter(value => value > 2);

console.log(arr); // [ 1, 2, 3, 4 ]

console.log(newArr); // [ 3, 4 ]
19.2.2 实现

filter函数做的事情就是过滤出符合条件的元素,对于filter的实现步骤和map的基本一致,不同之处在于其在数组中处理每个值的时候稍有区别。

Array.prototype.myFilter = function (fn) {
    if (typeof fn !== 'function') {
        throw new TypeError(`${fn} is not a function`);
    }

    // 获取该数组
    const arr = this;
    // 获取该数组长度
    const len = this.length >>> 0;
    // 新建一个新的数组用于放置该内容
    const temp = [];

    // 对数组中每个值进行处理
    for (let i = 0; i < len; i++) {
        // 处理时注意this指向
        const result = fn.call(arguments[1], arr[i], i, arr);
        result && temp.push(arr[i]);
    }

    return temp;
}

const arr = [1, 2, 3, 4];

const newArr = arr.myFilter(value => value > 2);

console.log(arr); // [ 1, 2, 3, 4 ]

console.log(newArr); // [ 3, 4 ]

19.3 reduce

img
19.3.1 基础

reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。

  1. reduce方法的用法如下所示:

const result = arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
  1. 小试牛刀

const arr = [1, 2, 3, 4];

const result = arr.reduce((accumulator, value) => accumulator + value);

console.log(result); // 10
19.3.2 实现

reduce为数组中的每一个元素依次执行callback函数,下面就来看看怎样实现自己的filter函数。实现步骤如下所示:

  1. 判断输入的第一个参数是不是函数

  2. 获取需要处理的数组内容

  3. 获取初始值

  4. 依次处理后续数组中的元素

  5. 返回累加器处理的结果

Array.prototype.myReduce = function(fn) {
    if (typeof fn !== 'function') {
        throw new TypeError(`${fn} is not a function`);
    }

    const arr = this;
    const len = arr.length >>> 0;
    let value;// 最终返回的值
    let k = 0;// 当前索引

    if (arguments.length >= 2) {
        value = arguments[1];
    } else {
        // 当数组为稀疏数组时,判断数组当前是否有元素,如果没有索引加一
        while (k < len && !( k in arr)) {
            k++;
        }
        // 如果数组为空且初始值不存在则报错
        if (k >= len) {
            throw new TypeError('Reduce of empty array with no initial value');
        }
        value = arr[k++];
    }
    while (k < len) {
        if (k in arr) {
            value = fn(value, arr[k], k, arr);
        }
        k++;
    }

    return value;
}

const arr = [1, 2, 3, 4];

const result = arr.myReduce((accumulator, value) => accumulator + value);

console.log(result); // 10

1.如果觉得这篇文章还不错,来个分享、点赞、在看三连吧,让更多的人也看到~

2.关注公众号执鸢者,领取学习资料,定期为你推送原创深度好文

3.关注公众号进群,里面大佬多多,一起向他们学习

1. 前端百题斩[001]——typeof和instanceof

2. 前端百题斩【002】——js中6种变量声明方式

3. 前端百题斩【003-004】——从基本类型、引用类型到包装对象

4. 前端百题斩【005】—— js中9种遍历对象的方法

5. 前端百题斩【006】——js中三类字符串转数字的方式

6. 前端百题斩【007】——js中必须知道的四种数据类型判断方法

7. 前端百题斩【008-009】——从JavaScript的代码执行过程到函数执行过程

8. 前端百题斩【010】——通俗易懂的JavaScript执行上下文

9. 前端百题斩【011】——通俗易懂的变量对象

10. 前端百题斩【012】——js中作用域及作用域链的真面目

11. 前端百题斩【013】——用“闭包”问题征服面试官

12. 前端百题斩【014】——js中的这些“this”指向都值得了解

13. 前端百题斩【015】——快速手撕call、apply、bind

14. 前端百题斩【016】——原型、构造函数和实例之间的奇妙关系

15. 前端百题斩【017】——一基础、二主线、双机制理解原型链

16. 前端百题斩【018】——从验证点到手撕new操作符

17. 一文彻底搞懂前端监控

18. 前端的葵花宝典——架构

19. canvas从入门到猪头

20. 前端工程师的一大神器——puppeteer

21. 2021 年前端宝典【超三百篇】

22. 前端也要懂机器学习(上)

23. 前端也要懂机器学习(下)

24. 学架构助力前端起飞

25. 假如只剩下canvas标签

26. Vue源码思想在工作中的应用

27. 一文搞定Diff算法

28. 百度、小红书三面,均遇“赛马”问题

29. 十五张图带你彻底搞懂从URL到页面展示发生的故事

30. 一文搞懂Cookie、Storage、IndexedDB

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值