JS 数组相关的循环函数,用得挺多,所以有些坑还是要去踩一下,先来看一道面试题。

注意:下面提到的不改变原数组仅针对基本数据类型。

面试题


模拟实现数组的 map 函数。

心中有答案了吗?我的答案放在最后。

map( callback( cur, index, arr ), thisArg )


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

  1. map 不改变原数组(可以在 callback 执行时改变原数组)

    let a = [1, 2, 3]
    let b = a.map(item => item*2) // 不改变原数组
    a // [1, 2, 3]
    b // [2, 4, 6] // 在 callback 执行时改变原数组
    a.map((cur, i, arr) => arr[i] *= 2)
    a // [2, 4, 6]
  2. 没有 return 时,返回undefined

    let c = a.map((cur, i, arr) => arr[i] *= 2)
    
    c // [undefined, undefined, undefined]
  3. 原数组中新增加的元素不会被 callback 访问

    let a = [1, 2, 3]
    let b = a.map((cur, i, arr) => {
    arr.push(arr.length + 1)
    return cur*2
    }) b // [2, 4, 6]
    a // [1, 2, 3, 4, 5, 6]

filter( callback( cur, index, arr ), thisArg )


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

这个没什么好说的,filter 只返回过滤后的新数组,依然不会改变原数组

let a = [1, 2, 3]
let b = a.filter(item => item % 2 == 0) a // [1, 2, 3]
b // [2]

需要注意的是,尽量不要在 filter 中直接return item

/* 一般情况是没问题的 */
let a = [1, 2, 3]
let b = a.filter(item => item) a // [1, 2, 3]
b // [1, 2, 3] /* false、0、undefined、null */
let c = [true, false, 0, undefined, null]
let d = c.filter(item => item) c // [true, false, 0, undefined, null]
d // [true]

一般情况下直接return item是没问题的,但遇到false、0、undefined、null这几个特殊值时,就会出问题。因为 filter 是根据return的值来判断返回的新数组是否要添加遍历到的原数组索引值,而不是直接在新数组中添加return的值。

简单来说,就是 filter 中的 callback 的 return 应该返回一个 boolean 值,true 即满足过滤条件,false 则不满足过滤条件。

forEach( callback( cur, index, arr ), thisArg )


forEach 方法对数组的每个元素执行一次提供的函数。

  1. forEach 无法中断,需要中断的则表明:不应该使用 forEach。当然,使用 try、catch 是可以实现中断的,但不推荐。

    let a = [1, 2, 3]
    
    try {
    a.forEach(item => {
    console.log(item)
    if (item % 2 == 0) throw new Error('hhh')
    })
    } catch (e) {
    console.log('中断')
    } /*
    1
    2
    中断
    */
  2. forEach 也是不会改变原数组的

    let a = [1, 2, 3]
    a.forEach(item => item*2)
    a // [1, 2, 3]

every( callback( cur, index, arr ), thisArg )


every 方法测试数组的所有元素是否都通过了指定函数的测试。

这个没什么好说的,但 every 和 some 都有个坑。

:空数组调用 every 会返回true

// 返回了 true
[].every(item => item > 0) // true

some( callback( cur, index, arr ), thisArg )


some 方法测试是否至少有一个元素通过由提供的函数实现的测试。

:空数组调用 some 会返回false

// 和 every 相反,这里返回了 false
[].some(item => item > 0) // false

reduce( callback( prev, cur, index, arr ), initVal )


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

  1. 如果没有提供initVal,reduce 会取数组中的第一个值为prev, 然后从数组索引 1 开始执行 callback,跳过第一个索引。如果提供initlVal,从索引 0 开始,previnitVal

  2. 如果数组为空且没有提供initVal会报错。

    [].reduce((prev, cur)=> cur) // TypeError

实现 map 函数


Array.prototype._map = function(callback, thisArg) {
if (typeof callback !== 'function') {
throw new TypeError(`${callback} is not a function`)
} let res = [] for (let i=0; i<this.length; i++) {
res.push(callback.call(thisArg, this[i], i, this))
} return res
}

JS: 数组的循环函数的更多相关文章

  1. js数组的splice函数

    一直没搞懂数组的splice函数,今天稍微测试了一下,了解了它的功能,在这里记录一下 1.测试 测试① var a = [1,2,3]; console.info(a.splice(1,1)); co ...

  2. JS数组(Array)处理函数总结

    1.concat() 连接两个或更多的数组该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本.例如: <script type="text/javascript"&g ...

  3. js数组之可变函数

    在js的数组中有两个方法为数组添加元素:1.push();2.unshift(),push函数是将元素添加到数组的末尾,现在不用说大家估计也能猜出来,unshift这个函数就是把元素添加到数组的开头的 ...

  4. js数组,数字函数,字符串函数,表单验证,hashMap,堆栈,日期函数,call函数

    1.javascript的数组API Js代码 收藏代码 //定义数组 var pageIds = new Array(); pageIds.push('A'); 数组长度 pageIds.lengt ...

  5. js数组之sort()函数

    一般我们使用sort函数进行数组的排序,sort()方法有一个可选参数,是用来确定元素顺序的函数.如果这个参数被省略,那么数组中的元素将按照ASCII字符顺序进行排序.如: var arr = [&q ...

  6. js 数组的forEach 函数

    var numbers = [4, 9, 16, 25]; function myFunction(item, index) { console.log("item:" + ite ...

  7. js数组 函数

    js数组 filter(),map(),some(),every(),forEach(),lastIndexOf(),indexOf() 文章1:http://www.jb51.net/article ...

  8. js 数组常用的操作函数整理

    平时多做企业应用开发,抱着实用为主,对前端技术理解得比较肤浅,下面就是肤浅地对 js 数组的属性和方法及对它操作的 jquery 方法做些记录: js 数组是 js 内建的一个非常强大数据类型,由于 ...

  9. 页面循环绑定(变量污染问题),js面向对象编程(对象属性增删改查),js字符串操作,js数组操作

    页面循环绑定(变量污染问题) var lis = document.querySelectorAll(".ul li") for ( var i = 0 ; i < lis. ...

随机推荐

  1. mysql字符串类型数据

    字符串类型是在数据库中存储字符串的数据类型,字符串类型包括char,varchar,text,enum和set. OK,我们来一个一个的看下上面提到的几种类型. char类型和varchar类型 ch ...

  2. 关于上级机构的冲突性测试bug修复

    描述: 1.上级机构可以为空. 2.机构添加时,选择了上级机构,在未提交前,另一用户将该机构删除,然后前一用户再提交表单,提示会保存成功,本操作应该保存失败. 思路:在上级机构不为空时,保存前进行查询 ...

  3. Architecture

    SMART Crossbar The SMART crossbar is the primary building block in a SMART NoC that enables straight ...

  4. 修改oracle用户密码为永不过期

    错误提示:ORA-28001: the password has expired (DBD ERROR: OCISessionBegin) 解决方法:修改密码为永不过期 (1)查看用户的proifle ...

  5. php常量 const 和 define

    常量是一个简单的标识符.在脚本执行期间该值不能改变(除了所谓的魔术常量,他们其实不是常量).常量默认大小写敏感.通常常量标识符总是大写的. 可以用define()函数来定义常量.在php5.3.0以后 ...

  6. fPLL结构及动态配置

    输入参考时钟 从上图可以看到参考时钟输入的几种类型.   注意:fPLL的校正是由CLKUSR来驱动的,这个时钟必须要保持稳定. 参考时钟利用器     N计数器 N计数器会把参考时钟利用器输出进行分 ...

  7. String、Stringbuffer、Stringbuilder三者之间的区别

    1.首先说运行速度,速度由快到慢排列:StringBuilder > StringBuffer > String String最慢的原因: String为字符串常量,而StringBuil ...

  8. 在linux中如何解压.tgz

    然后首先:打开终端 1,进入下载路径下,比如我的就是进入Downloads下. 输入命令: cd Downloads 2,解压到当前文件夹 输入:tar zxvf  文件名.tgz -C ./     ...

  9. 【python】鼠标操作

    [python]鼠标操作 推荐地址:http://www.cnblogs.com/fnng/p/3288444.html --------------------------------------- ...

  10. hdu 5058 set应用

    http://acm.hdu.edu.cn/showproblem.php?pid=5058 set应用 水题 #include <cstdio> #include <cstdlib ...