JavaScript-数组操作方法汇总

2023-11-06

一直以来都想把js中操作数组的所有方法进行一个汇总,今天终于完成了,希望可以给大家带来一些便利!

一、ES5数组操作方法

  1. 转换方法
    toString():返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串
    toLocaleString(): 与toString()功能一样,但底层调用但是toLocaleString()方法
    valueOf():返回数组
    join():只接收一个参数,即用作分隔符的字符串,然后返回包含所有数组项的使用传入分隔符拼接的字符串。

    var peoples = ["Dancy", "Echo", "Frocle"];
    console.log(peoples.toString()); // Dancy,Echo,Frocle
    console.log(peoples.valueOf()); // ["Dancy", "Echo", "Frocle"]
    console.log(peoples.toLocaleString()); // Dancy,Echo,Frocle
    console.log(peoples.join()); // Dancy,Echo,Frocle
    console.log(peoples.join("-")); // Dancy-Echo-Frocle
    
  2. 栈方法
    pushpop方法配合使用,可以实现栈
    push(): 将传入的数据添加到数组末尾,并返回修改后数组的长度
    pop():从数组末尾移除最后一项,减少数组的 length 值,然后返回移除的项。

    var peoples = ["Dancy", "Echo", "Frode"];
    var numl = peoples.push("Bob");
    var num2 = peoples.push("Mary");
    console.log("push返向的数组长度:",numl, num2); // push返回的数组长度:4 5
    console.log(peoples); // ["Dancy", "Echo", "Frode", "Bob", "Mary"]
    
    var val = peoples.pop();
    console.log("pop 返回的 val:", val); // pop返回的val: Mary
    console.log(peoples); //  ["Dancy", "Echo", "Frode", "Bob"]
    
  3. 队列方法
    push()shift()配合使用,或者unshift()pop()配合使用可以实现队列
    shift(): 从数组开头移除第一项,减少数组的 length 值,然后返回移除的项。
    unshift(): 在数组开头添加任意个项并返回新数组的长度。

    var peoples = ["Dancy", "Echo", "Frode", "Bob"];
    var shiftValue = peoples.shift(); 
    console.log("shiftValue:", shiftValue); // shiftValue: Dancy
    console.log(peoples); ["Echo", "Frode", "Bob"]
    
    var unshiftVal = peoples.unshift("Yvonne"); 
    console.log("unshiftVal:", unshiftVal); // unshiftVal: 4
    console.log(peoples); // ["Yvonne", "Echo", "Frode", "Bob"]
    
  4. 重排序方法
    reverse(): 反转原数组,并返回被反转修改后的原数组

    var arr = [1, 2, 3, 4, 5]; 
    var newArr = arr.reversed); 
    console. log("newArr:", Arr); // newArr: [5, 4, 3, 2, 1] 
    console.log("arr:", arr); // arr: [5, 4, 3, 2, 1]
    newArr.push(6); 
    console.log(arr); // [5, 4, 3, 2, 1, 6]
    

    sort():在默认情况下,sort()方法按升序排列数组项——即最小的值位于最前面,最大的值排在最后面。

    为了实现排序,sort()方法会调用每个数组项的 toString()转型方法,然后比较得到的字符串,以确定如何排序。即使数组中的每一项都是数值,sort()方法比较的也是字符串。

    var arr = [0, 1, 5, 10, 15]; 
    arr.sort(); 
    alert(arr); //0,1,10,15,5 
    

    sort的用法:sort()方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面。

    比较函数接收两个参数,如果第一个参数应该位于第二个之前则返回一个负数,如果两个参数相等则返回 0,如果第一个参数应该位于第二个之后则返回一个正数。

    function compare(a, b) { 
     if (a < b) { 
     return -1; 
     } else if (a > b) { 
     return 1; 
     } else { 
     return 0; 
     } 
    } 
    var arr = [0, 1, 5, 10, 15]; 
    arr.sort(compare);
    alert(arr); //0,1,5,10,15 
    

    比较函数的另一种写法:

    function compare(a, b) { 
        return a - b; // 若为b - a则sort排序结果为降序
    } 
    var arr = [1, 5, 15, 65, 22];
    arr.sort(compare);
    console.log(arr); // [1, 5, 15, 22, 65]
    
  5. 操作方法
    concat():会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。

    在没有给 concat()方法传递参数的情况下,它只是复制当前数组并返回副本。

    如果传递给 concat()方法的是一或多个数组,则该方法会将这些数组中的每一项都添加到结果数组中。

    如果传递的值不是数组,这些值就会被简单地添加到结果数组的末尾

    var peoples = ["Dancy", "Echo", "Frocle"]; 
    var newPeoples = peoples.concat("Yvonne", ["Mary", "Bob"]); 
    console.log(peoples); // ["Dancy", "Echo", "Frocle"];
    console.log(newPeoples); // ["Dancy", "Echo", "Frocle", "Yvonne", "Mary", "Bob"];
    

    slice(): 基于当前数组中的一或多个项创建一个新数组。slice()方法可以接受一或两个参数,即要返回项的起始和结束位置。

    在只有一个参数的情况下,slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。

    如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。
    注意,slice()方法不会影响原始数组。

    var peoples = ["Dancy", "Echo", "Frocle", "Yvonne", "Mary", "Bob"]; 
    var arr1 = peoples.slice(1); 
    var arr2 = peoples.slice(1,4); 
    console.log(arr1); // ["Echo", "Frocle", "Yvonne", "Mary", "Bob"]
    console.log(arr2); // ["Echo", "Frocle", "Yvonne"]
    

    splice():
    删除:指定 2 个参数,要删除的第一项的位置和要删除的项数。返回被删除的元素组成的数组。

    插入:提供 3 个参数,起始位置、0(要删除的项数)、要插入的项。如果要插入多个项,可以再传入第四、第五,以至任意多个项。由于被删除项为0,故返回空数组

    替换:指定 3 个参数,起始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等,返回被删除的元素组成的数组。

    splice()方法始终都会返回一个数组,该数组中包含从原始数组中删除的项(如果没有删除任何项,则返回一个空数组)。

    var peoples = ["Dancy", "Echo", "Frocle"]; 
    var removed = peoples.splice(0, 1); // 删除第一项
    console.log(peoples); // ["Echo", "Frocle"]
    console.log(removed); // ["Dancy"] 返回的数组中只包含一项
    
    removed = peoples.splice(1, 0, "Mary", "Bob"); // 从位置 1 开始插入两项
    console.log(peoples); // ["Echo", "Mary", "Bob", "Frocle"]
    console.log(removed); // 返回的是一个空数组
    
    removed = peoples.splice(1, 1, "Yvonne", "Chris"); // 插入两项,删除一项
    console.log(peoples); // ["Echo", "Yvonne", "Chris", "Bob", "Frocle"]
    console.log(removed); // ["Mary"],返回的数组中只包含一项
    
  6. 位置方法
    indexOf():从数组的开头(0位置)开始向后查找
    lastIndexOf():从数组的末尾开始向前查找

    这两个方法都接收两个参数:要查找的项和(可选)表示查找起点位置的索引。这两个方法都返回要查找的项在数组中的位置下标,或者在没找到的情况下返回-1。

  7. 迭代方法
    every(): 测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。注意:若收到一个空数组,此方法在一切情况下都会返回true。

    const isBelow40 = (currentValue) => currentValue < 40;
    const arr1 = [1, 30, 39, 22, 10, 13];
    const arr2 = [1, 30, 39, 55, 10, 13];
    
    console.log(arr1.every(isBelow40)); // true
    console.log(arr2.every(isBelow40)); // false
    console.log([].every(isBelow40)); // true
    

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

    const peoples = ['Dancy', 'Yvonne', 'Echo', 'Chris', 'Bob', 'Mary'];
    const result = peoples.filter(name => name.length > 4);
    console.log(result); // ["Dancy", "Yvonne", "Chris"]
    

    forEach(): 对数组的每个元素执行一次给定的函数。

    const arr = ['a', 'b', 'c'];
    arr.forEach(val => console.log(val.toUpperCase()));
    // A
    // B
    // C
    

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

    const arr = [1, 5, 10, 15];
    const newArr = arr.map(x => x * 100);
    console.log(newArr); // [100, 500, 1000, 1500]
    

    some(): 测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回的是一个Boolean类型的值。注意:如果用一个空数组进行测试,在任何情况下它返回的都是false。

    const array = [1, 2, 3, 4, 5];
    const even = (element) => element % 2 === 0;
    console.log(array.some(even)); // true
    
  8. 归并方法
    reduce(): 对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。

    使用:
    arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
    callback: 执行数组中每个值 的函数,包含四个参数:
        accumulator 累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue(见于下方)。
        currentValue 数组中正在处理的元素。
        index 可选,数组中正在处理的当前元素的索引。 如果提供了initialValue,则起始索引号为0,否则从索引1起始。
        array可选,调用reduce()的数组
    initialValue 可选, 初始值,作为第一次调用callback函数时的第一个参数的值。如果没有提供初始值,则将使用数组中的第一个元素。 
    在没有初始值的空数组上调用 reduce 将报错。
    
    const arr = [1, 2, 3, 4];
    const reducer = (accumulator, currentValue) => accumulator + currentValue;
    
    console.log(arr.reduce(reducer)); // 10
    console.log(arr.reduce(reducer, 5)); // 15 5为initialValue
    // console.log([].reduce(reducer)); // 报错 Error: Reduce of empty array with no initial value
    // 注意:如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue,从索引0开始。
    

    reduceRight(): 接受一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值。

    const arr = [[0, 1], [2, 3], [4, 5]].reduceRight(
      (accumulator, currentValue) => accumulator.concat(currentValue)
    );
    console.log(arr); // [4, 5, 2, 3, 0, 1]
    

二、ES6新增数组操作

  1. Array.from(): 用于将类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构SetMap)转为真正的数组

    let persons = {
        '0': 'Dancy',
        '1': 'Mary',
        '2': 'Echo',
        length: 3
    };
    
    // ES5的写法
    var arr1 = [].slice.call(arrayLike); // ['Dancy', 'Mary', 'Echo']
    // ES6的写法
    let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
    

    实际应用中,常见的类似数组的对象是DOM操作返回的NodeList集合,以及函数内部的arguments对象。Array.from都可以将它们转为真正的数组。

  2. 扩展运算符(…): 可以将某些数据结构转为数组

    // arguments对象
    function fn() {
      var args = [...arguments]; // 展开参数
    }
    
    // NodeList对象
    [...document.querySelectorAll('div')]
    

    扩展运算符背后调用的是遍历器接口(Symbol.iterator),如果一个对象没有部署这个接口,就无法转换。

  3. Array.of():用于将一组值,转换为数组。

    Array.of(1, 2, 3) // [1,2,3]
    
  4. 数组实例的copyWithin()
    将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。

    Array.prototype.copyWithin(target, start = 0, end = this.length)
    // target(必需):从该位置开始替换数据。
    // start(可选):从该位置开始读取数据,默认为0。如果为负值,表示倒数。
    // end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
    // 这三个参数都应该是数值,如果不是,会自动转为数值。
    
    [1, 2, 3, 4, 5].copyWithin(0, 3)
    // [4, 5, 3, 4, 5]
    
  5. 数组实例的find()findIndex()
    find(): 用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined。

    [1, 4, -5, 10].find((n) => n < 0) // -5
    

    findIndex():返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。

    [1, 5, 10, 15].findIndex(function(value, index, arr) {
      return value > 9;
    }) // 2
    

    这两个方法都可以接受第二个参数,用来绑定回调函数的this对象。另外,这两个方法都可以发现NaN,弥补了数组的IndexOf方法的不足。

    [NaN].indexOf(NaN)// -1
    [NaN].findIndex(y => Object.is(NaN, y)) // 0 Object.is() 方法判断两个值是否为同一个值。
    
  6. 数组实例的fill()
    使用给定值,填充一个数组。fill方法可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。

    ['a', 'b', 'c'].fill(6) // [6, 6, 6]
    new Array(2).fill(5) // [5, 5]
    
  7. 数组实例的entries()keys()values()
    用于遍历数组。它们都返回一个遍历器对象,可以用for…of循环进行遍历,唯一的区别是:
    keys()是对键名的遍历
    values()是对键值的遍历
    entries()是对键值对的遍历

    for (let index of ['a', 'b'].keys()) {
      console.log(index);
    }
    // 0
    // 1
    
    for (let elem of ['a', 'b'].values()) {
      console.log(elem);
    }
    // 'a'
    // 'b'
    
    for (let [index, elem] of ['a', 'b'].entries()) {
      console.log(index, elem);
    }
    // 0 "a"
    // 1 "b"
    

    如果不使用for...of循环,可以手动调用遍历器对象的next方法,进行遍历。

    let letter = ['a', 'b', 'c'];
    let entries = letter.entries();
    console.log(entries.next().value); // [0, 'a']
    console.log(entries.next().value); // [1, 'b']
    console.log(entries.next().value); // [2, 'c']
    
  8. 数组实例的includes()
    返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似。该方法属于ES7,但Babel转码器已经支持。
    第二个参数表示搜索的起始位置,默认为0。
    如果第二个参数为负数,则表示倒数的位置。如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。

    [1, 2, 3].includes(2);     // true
    [1, 2, 3].includes(4);     // false
    [1, 2, NaN].includes(NaN); // true
    

三、模拟实现数组的部分方法

  1. forEach()

    //模拟forEach函数
    function forEach(array, fn) {
      for (let i = 0; i < array.length; i ++) {
        fn(array[i]) //用传进来的函数处理数组中的每一个元素
      }
    }
    // 测试forEach
    let arr1 = [1, 2, 3, 4, 5]
    forEach(arr1, (item) => { // 接收从forEach函数中回传的参数
      console.log(item)
    })
    
  2. filter()

    // 模拟filter
    function filter (array, fn) {
      let results = [] // 保存满足条件的值
      for (let i = 0; i < array.length; i ++) {
        if (fn(array[i])) { // 满足fn中的条件时,push进results数组
          results.push(array[i])
        }
      }
      return results
    }
    // 测试filter
    let arr2 = [1, 3, 6, 4, 10]
    let results = filter(arr2, (item) => { // 获取数组中大于5的项并以数组形式返回
      return item > 5 
    })
    console.log(results) // 输出[6, 10]
    
  3. once()

    // 模拟once函数,让函数只执行一次
    function once (fn) {
      let done = false
      return function () { // 这是返回的匿名函数
        if (!done) {
          done = true
          // 这里的this就是fn,使用apply的目的是将匿名函数的参数展开并传给fn
          return fn.apply(this, arguments) 
        }
      }
    }
    // 测试once
    let pay = once((money, other) => { // 通过apply展开了这里的参数,money、other
      console.log(`支付了:${money} RMB`)
      console.log(money, other)
    })
    pay(5, 6)
    pay(5)
    pay(5)
    pay(5)
    // 调用了多次pay,但只执行了一次
    
  4. map()

    // 模拟map
    // 对数组中对每一个元素进行遍历,对每一个元素进行处理,并返回处理结果
    const map = (array, fn) => {
      let results = []
      for (let item of array) { // ES6 新遍历方式,对for循环对抽象,比for循环更简洁
        // 将通过fn处理后对数组元素放入新数组
        results.push(fn(item))
      }
      return results
    }
    // map测试
    let arr1 = [1, 2, 3, 5, 6]
    arr1 = map(arr1, v => v * v)
    console.log(arr1) // [1, 4, 9, 25, 36]
    
    
  5. every()

    // 模拟every
    // 判断数组中的每一个元素是否都匹配传入函数中指定都条件
    const every = (array, fn) => {
      for (let item of array) {
        if (!fn(item)) {
         return false
        }
      }
      return true
    }
    // 测试every
    let arr2 = [1, 3, 6, 9, 23]
    let arr3 = [1, 3, 3, 0, 2]
    let result1 = every(arr2, v => v < 5)
    let result2 = every(arr3, v => v < 5)
    console.log(result1) // false
    console.log(result2) // true
    
  6. some()

    // 模拟some
    // 检测数组中是否有元素满足传入函数中指定的条件
    const some = (array, fn) => {
      for (let item of array) {
        if (fn(item)) {
          return true
        }
      }
      return false
    }
    // 测试some
    let arr4 = [1, 2, 3, 4, 5]
    let r = some(arr4, v => v % 2 === 0)
    console.log('some:', r) // true
    

四、总结

  1. 不会改变原数组的方法

    toString()
    toLocaleString()
    valueOf()
    join()
    slice()
    concat()
    indexOf()
    lastIndexOf()
    
  2. 会改变原数组的方法

    push()
    pop()
    shift()
    unshift()
    reverse()
    sort()
    splice()
    
  3. 数组遍历方法

    every()
    filter()
    forEach()
    map()
    some()
    reduce()
    reduceRight()
    数组实例的entries(),keys()和values()
    

参考书籍:《Javascript高级程序设计(第三版)》
参考网站:
JavaScript MDN
ES6 文档

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaScript-数组操作方法汇总 的相关文章

  • 如何将正文中的数字替换为波斯数字?

    我想将 html 内容中的每个数字转换为波斯数字 而不会对页面元素产生其他影响 例如 div style color c2c2c2 text number 1 span text number 2 span div text number
  • 如何在 Angular JS 中显示以字节数组形式接收的图像

    我有一个将返回图像的服务器端应用程序 这些是响应标头 Content Disposition attachment filename 8822a009 944e 43f4 999b d297198d302a 1 0 low res Cont
  • Nodemon - 使用配置文件指定扩展监视列表

    有没有办法使用配置文件而不是命令行来指定监视列表 Nodemon 文档中的命令行方法 我尝试使用nodemon json配置文件包含以下内容 ext js json hbs html 返回 扩展名匹配 错误 然后我尝试将配置添加到packa
  • 使用 JavaScript 将数字缩写(5.2k、1.7m 等)转换为有效整数

    我有一个 Google 文档 其中有一列包含用 速记 编写的各种数字 例如 5k for 5 000 86 62k for 86 620 4 1m for 4 100 000 1 2b for 1 200 000 000 我想使用 Java
  • 调整表格上的列宽

    目前 如果表格的宽度不大于容器的宽度 我可以调整表格列的大小 我希望发生的是在调整列大小时表格的宽度增加 以便滚动条出现在表格下方 基本上允许我调整大小而不受容器宽度的限制 这是一个小提琴 https jsfiddle net thatOn
  • 使用Web蓝牙API时找不到移动设备

    我正在学习 Web 蓝牙 API 使用 google 开发控制台 我无法找到我的移动设备 还尝试了 github 上提供的演示 https github com WebBluetoothCG demos https github com W
  • 现在 JavaScript 的无限循环会导致浏览器崩溃吗?

    我正在学习 JavaScript 对编程很陌生 碰巧遇到了这些无限循环 据说这些循环会永远持续下去并使浏览器崩溃 但是当我用这些代码创建一个循环时 i 0 while i lt 10 document write i 浏览器只是继续加载它
  • 如何使用canvas获取html5中的视频截图

    您好 是否可以使用 html 5 canvas 捕获正在播放的视频的屏幕截图 看起来这里是可能的 http html5doctor com video canvas magic http html5doctor com video canv
  • 在高图表中突出显示一系列条形图中的一个条形图?

    我有一个图表 显示堆叠和分组的条形图 类似于这个演示 http www highcharts com demo column stacked and grouped 有没有办法从 JavaScript 代码中使系列之一中的其中一个栏突出显示
  • 如何防止机器人程序和垃圾邮件 API 请求?

    我正在使用react native 开发一个Android 应用程序 该应用程序与我正在为该应用程序开发的API 进行通信 该 API 是使用 Laravel 和 Laravel Passport 构建的 我知道 Android 应用程序可
  • 如何让 Rails 资产管道生成源地图?

    我想让 Rails 与编译后的 CoffeeScript 缩小的 JS 一起生成源映射 以便更好地记录错误 不过 网上似乎还没有关于如何执行此操作的全面文档 有人这样做过吗 我使用 Rails 3 2 和 Heroku Rails 支持缩小
  • JavaScript 中最大长度的正则表达式

    如何限制与正则表达式匹配的字符串的长度 我假设var sixCharsRegEx 6 7 只匹配长度为 6 或 7 的字符串 but no http jsfiddle net FEXbB http jsfiddle net FEXbB 我缺
  • 如何从 angularJS 模板调用encodeURIComponent?

    我的 Angular JS 模板中有一个块 a href foos foo id foo name a 但是 foo id 属性有时可能包含时髦字符 我想做这样的事情 a href foos encodeURIComponent foo i
  • 获取 Html.TextBoxFor 字段的 HTML id

    有没有办法在 Javascript 中获取 ASP NET MVC 控件生成的客户端 ID Html TextBoxFor m gt m Name 像这样 Html IdFor m gt m Name
  • Firefox 扩展中的 localStorage

    我正在尝试从 Firefox 扩展访问页面的 localStorage 我的理解是content给出了参考window当前页面的 当我尝试访问页面的 localStorage 时content localStorage 我想我正在得到它的参
  • 所有人共享的 First Load JS 在 next.js 中相当重

    I have a project on Next js framework and the problem is that First Load JS shared by all pages is rather heavy I want t
  • 使用 TypeScript / Angular2 循环对象的键/值[重复]

    这个问题在这里已经有答案了 如何使用 TypeScript 迭代对象并能够访问键和值 我的 json 对象看起来像这样 clients 123abc Forename Simon Surname Sample 456def Forename
  • 用圆形雷达数学方法表示点

    我正在编写一个简单的应用程序 它可以向您显示您周围的朋友 但不是在法线地图中 而是在像 UI 这样的真正圆形雷达上 https i stack imgur com Au3IP png https i stack imgur com Au3I
  • .js.erb VS .js

    将 Rails 应用程序的 javascript 放入 js erb 文件而不只是将其放入 application js 文件有什么好处 我有一个企业创建按钮 因此我应该将代码放入 create js erb 文件中 还是使用以下方法将其放
  • Sencha-touch :保存登录名/密码(保存会话,多任务)

    我有一个 Java Web 应用程序 其中移动部分是用 Sencha touch 开发的 当我启动 sencha touch 应用程序时 她询问我的登录名 密码 因为该应用程序的访问受到限制 但是我想保存用户的登录名 密码 sencha t

随机推荐