JavaScript数组方法持续更新

JavaScript数组方法持续更新

作为 js 的重要一员,一定要好好了解一番,若有理解不到之处,还望不吝指教。

何为数组,是有序的集合。

一、如何判断是否是数组


  1. Array.isArray() 字面上的理解,是不是一个数组。

    let arr = []
    let str = '[]'
    Array.isArray(arr) // true
    Array.isArray(str) // false
    
  2. instanceof 是不是 Array 的实例。

    let arr = []
    let str = '[]'
    arr instanceof Array // true
    str instanceof Array // false
    
  3. constructor , 实例对象的隐式原型指向对象的构造函数。

    let arr = []
    arr.constructor === Array // true
    
  4. Object.prototype.toString.call(arr) === '[object Array]'

    let arr = []
    Object.prototype.toString.call(arr) === '[object Array]' // true
    

二、创建数组


  • 字面量

    let arr = []
    
  • new Array()

    let arr = new Array()
    
  • split()

    let str = '1,2,3'
    let arr = str.split(',')
    
  • Array.from()

    // 将字符串转换成数组
    let str = '123'
    let arr = Array.from(str) // ["1","2","3"]
    
    // 将 arguments 伪数组转换为数组
    Array.from(arguments)
    
    // 将 dom 元素伪数组转换为数组
    Array.from(document.querySelectorAll('div'))
    

    Array.from 接受3个参数

    • 第一个参数必填,需要转换的对象
    • 第二个可选,接受一个回调函数,数组中的每一项都会回调该函数
    • 第三个可选,绑定回调函数的 this 指向
  • Array.of() 无论什么类型,包裹一层变成数组

    Array.of() 
    Array.of('') 
    Array.of(null)
    Array.of(undefined) 
    Array.of(NaN) 
    Array.of(()=>{}) 
    Array.of({}) 
    Array.of(123) 
    

三、数组的方法


关注一个方法或者函数,主要关注以下几点

  1. 参数
  2. 返回值

常用的数组方法

​ 不改变原数组

​ forEach map filter some every find findIndex concat indexOf lastindexOf slice flat includes

​ join reduce

​ 改变原数组

​ push unshift pop shift splice fill sort reverse

  • forEach()

    /*  接受 2 个参数
     *    第一个参数必填,回调函数
     *    第二个参数,绑定回调函数的 this 指向, (例子里的 obj)
     */
    Array.forEach( (item,index,Array) => {
      // item 表示数组当前循环到的项
      // index 表示数组当前循环项的下标值
      // Array 表示原数组
    },obj)
    

    forEach 不能中断循环(break),只能跳过当前循环项,进入下一项的循环。

    该方法返回值为 undefined

  • map() , 参数同 forEach 方法。

    // 不能直接跳出循环 break 会报错, return 也不行
    let arr = [1,2,3]
    let res = arr.map((item)=>{
     return item + 1
    })
    

    返回值为一个新的数组,不改变原来的数组。

  • filter(), 一般用来过滤数组中的元素,参数同 forEach 方法

    let obj = {}
    let arr = [
      {
        id: 1,
      },
      {
        id: 2,
      },
      {
        id: 3,
      },
    ]
    let newArr = arr.filter((item, index, Array) => {
      // 必须 return ,且新数组只会含有条件为 true 的项
      return item.id == 2
    }, obj)
    console.log(newArr) // [{id: 2}]
    

    返回值为一个新数组,不改变原数组

  • some() ,参数同 forEach

    arr.some( (item, index, Array) => {
       // 有一项满足条件,则返回 true ,剩余的项不在参与循环;没有满足条件,返回 false
       // 有点 逻辑 || 的意思,只是参与的项不同。
       return item.id === 2
    }, obj)
    

    返回值 Boolean 类型, true or false

  • every(),参数同 forEach

    /* 和 some() 方法相似,有一项是 false 则终止循环,返回 false,每一项都是 true ,返回 true
     * 这个完全和 && 的思想一致
     */
    

    返回值 Boolean 类型, true or false

    tips: 空数组是个特例,始终返回 true

  • find(),参数同 forEach

    /* 
     *  找到匹配的项则返回第一个匹配项,循环终止;找不到则返回 undefined
     */
    

    返回值,匹配的项 或者 undefined

  • findIndex(),参数同forEach

    // 匹配到选项则返回第一个匹配项的索引,循环终止,否则返回 -1
    

    返回值,匹配到的下标值 或者 -1

  • push()

    // 在数组的最后增加元素
    let arr = [1,2]
    arr.push(3) // 一个参数
    let res = arr.push(4,5,6) // 多个参数
    console.log(res) // [1, 2, 3, 4, 5, 6]
    console.log(arr) // 6
    

    返回数组的长度,并改变原数组

  • unshift()

    let arr = [1,2]
    arr.unshift(0) // 3
    

    返回数组的长度,并改变原数组

  • pop(), 不需要参数

    // 从数组的最后开始删除一个元素
    let arr = [1,2]
    arr.pop()  // 2
    

    返回被删除元素,空数组删除返回 undefined,改变原数组,

  • shift(), 不需要参数

    // 从数组的开头开始删除一个元素
    let arr = [1,2]
    arr.shift() // 1
    

    返回被删除元素,空数组删除返回 undefined,改变原数组,

  • concat(), 拼接数组

    let arr = [1, 2]
    let arr1 = [3, 4]
    let arr2 = [5, 6]
    let newArr = arr.concat(arr1, arr2) // 数组的拼接
    let newArr2 = newArr.concat() // 数组的浅拷贝
    

    返回值为新的数组, 不改变原来的数组

  • indexOf()lastIndexOf()

    // 找到第一次匹配元素的索引值,否则返回 -1
    let arr = [1,2,3,4]
    arr.indexOf(2, 0) // 从索引为 0 的位置开始向数组的末尾查找
    arr.lastIndexOf(2, arr.length-1) // 从索引为 arr.length-1 的位置开始向数组的开头查找
    

    返回值为匹配的下标 或者 -1

  • slice(), 浅拷贝数组

    let arr = [1,2,3,4,5,6]
    // 包含开始位置, 不包含结束位置
    arr.slice(1,2) // [2]
    

    返回值 新的数组, 不改变原数组

  • splice(), 万金油的存在,增、删、改功能。

    let arr = [1, 2, 3]
    
    /*  删除功能,任意位置删除
     *  参数1. 开始的索引位置,包含该位置
     *  参数2. 删除的个数
     *  返回值:返回删除的元素的一个数组,改变原数组
     */
    arr.splice(0, 1)  // [1]
    console.log(arr)  // [2, 3]
    
    /*  增加功能,任意位置增加元素
     *  参数1. 开始的索引位置,也可以理解为新数组的索引位置上插入新的项。
     *  参数2. 删除个数为 0
     *  参数3. 增加的项
     *  返回值:空数组,改变原数组
     */
    arr.splice(1, 0, 1, 2, 3)  // []
    console.log(arr)  // [2, 1, 2, 3, 3]
    
    /*  修改功能,任意位置修改,这个就是增加功能的变形
     *  参数1. 开始索引位置,包含该位置
     *  参数2. 替换的个数 n,包含从索引参数1开始在内的向后 n 项将会从数组去除
     *  参数3. 替换的项, 在数组索引参数1位置,向后插入替换的项
     *  返回值: 空数组,改变原数组
     */
    arr.splice(1, 2 ,{id:1},{id:2})
    
    

    主要是参数的灵活运用,组成不同的功能,很实用。

  • copyWithin()

    /* 从数组内部替换自身项
     * 参数1. 替换元素开始的位置
     * 参数2. 从该索引开始复制数据,默认是0
     * 参数3. 复制数据结束的索引值,不包含该位置,默认到数组的结束
     * 返回值:修改后的新数组
     */
    let arr = [1, 2, 3, 4]
    arr.copyWithin(0,1,2) // [2,2,3,4]
    

    返回值为新的数组,改变原数组

  • fill()

    /*  填充数组
     *  参数1. 用来填充数组的值
     *  参数2. 起始索引值,默认是 0 
     *  参数3. 终止索引值,不包含该项,默认是数组的长度
     */
    let arr = []
    arr.fill(1, 0, 10) // 无法改变空数组,只能改变已有的项
    arr = [1, 2, 3, 4]
    arr.fill(5, 1 ,2) // [1,5,3,4]
    

    返回值为改变后的数组,改变原数组

  • flat()

    /*  多维数组变成一维数组
     *  参数 指定展开嵌套数组的深度,Infinity 表示任意深度
     *  不传可以去除数组中的空项
     *  返回值:新的的数组,不改变原数组
     */
    let arr = [1, 2, [3, 4]]
    arr.flat(1)   // [1, 2, 3, 4]
    
    let arr1 = [1, 2, 3, , ,4]
    arr1.flat() // [1, 2, 3, 4]
    

    返回值:新的的数组,不改变原数组

  • flatMap(),参数同 forEach

    /*  循环数组,每一项执行一个函数,最终执行以下flat()方法
     *  返回值:新的数组,不会改变原数组 
     */
    let arr = [1, 2]
    arr.flatMap( (item) => {
        [item, item * 2]
    }) // [1,2,2,4]
    

    flatMap 只能展开一层数组

  • includes()

    /*  判断数组是否含有某个指定的值
     *  参数1. 包含项
     *  参数2. 检索的开始位置,包含该位置
     *  返回值:包含返回 true , 不包含返回 false
     */
    console.log([1, 2, 3].includes(3));    // true
    console.log([1, 2, 3].includes(3, 3))  // false
    console.log([1, 2, 3].includes(3, 2))  // true
    

    也可用于字符串的检索,区分大小写

  • sort()

    /*  排序
     *  参数1. 
     *  参数2. 
     *  规则
     *    - 不传值,则是转化为字符串逐位比较 ASCII 大小
     *    - 接收一个函数,函数有个两个参数 a b
     *        若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
     *        若 a 等于 b,则返回 0。
     *        若 a 大于 b,则返回一个大于 0 的值。
     *  返回值:新的排序后的数组
     */
    let arr = [1,5,2,10]
    arr.sort((a, b) => {
        // a - b 返回值为正数,则交换两项的位置
        return a - b
    }) // [1,2,5,10] 从小到大
    arr.sort((a, b) => {
        return b - a
    }) // [10,5,2,1] 从大到小
    

    返回值为有序的新数组,改变原数组

  • reverse()

    let arr = [1, 2, 3]
    arr.reverse() // [3, 2, 1]
    

    反转数组,改变原数组

  • toLocaleString()toString()

    /*  将数组的每一项使用 toLocaleString 或者 toString
     *  不同点是语言环境的不同
     *  返回值:字符串,不改变原数组
     */
    let arr = [1, 'a', { id: 1 }, new Date()]
    // 1,a,[object Object],2020/5/22 下午2:44:40
    console.log(arr.toLocaleString())
    // 1,a,[object Object],Fri May 22 2020 14:44:40 GMT+0800 (中国标准时间)
    console.log(arr.toString())
    

    返回值:字符串,不改变原数组

  • join()

    /*  将数组使用特定的符号进行分割
     *  返回值:字符串,不改变原数组
     */
    let arr = [1, 2, 3]
    arr.join() // 1,2,3
    arr.join('') //123
    arr.join('*') //1*2*3
    

    和 split 更配哦

  • reduce(), 实用且重要的方法。

    /*  累加和累计这种描述特贴切
     *  参数1. 一个处理函数,接收 4 个参数
     *      - pre 第一次为参数2的值,然后是每次 处理函数 返回的值
     *    — val 当前循环项
     *    - index 当前循环项索引
     *    — arr 当前数组
     *  参数2. 第一次 pre 的值,默认是数组的第一个值。
     */
    let str = '好好学习天天向上'
    let arr = str.split('')
    let i = 0
    let res = arr.reduce((pre, val, index, arr) => {
      console.log(i++)
      console.log(`pre:${pre}`)
      console.log(`val:${val}`)
      return pre + val
    }, '我会')
    console.log(res) // 我会好好学习天天向上
    

    返回值为累计的结果,不会改变原数组

  • reduceRight()

    和 reduce 的结果一样,不同的是从数组的最后开始。

参考


[ MDN ]:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array
[ 掘金 ]: https://juejin.im/post/5d1ff6def265da1b855c777f#heading-22

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339