js中数组的方法总结及一些使用场景

一、添加、移除数组元素

splice(修改原数组)

作用:添加、删除和插入元素
语法:

它从索引 start 开始修改 arr:删除 deleteCount 个元素并在当前位置插入 elem1, …, elemN。最后返回被删除的元素所组成的数组。
arr.splice(start[, deleteCount, elem1, …, elemN])

删除:(注:当只填写了 splice 的 start 参数时,将删除从索引 start 开始的所有数组项)

let arr = ["I", "study", "JavaScript"];
arr.splice(1, 1); // 从索引 1 开始删除 1 个元素
alert( arr ); // ["I", "JavaScript"]

删除并添加元素:

let arr = ["I", "study", "JavaScript", "right", "now"];
// 删除数组的前三项,并使用其他内容代替它们
let removed=arr.splice(0, 3, "Let's", "dance");
alert( removed ); // "I", "study" ,"JavaScript" <-- 被从数组中删除了的元素
alert( arr ) // 现在 ["Let's", "dance", "right", "now"]

插入元素而不删除任何元素:(deleteCount 设置为 0)

let arr = ["I", "study", "JavaScript"];

// 从索引 2 开始
// 删除 0 个元素
// 然后往索引2的前方插入 "complex" 和 "language"
arr.splice(2, 0, "complex", "language");

alert( arr ); // "I", "study", "complex", "language", "JavaScript"

slice(产生新数组)

作用:截取某一范围到新数组
语法:

将所有从索引 start 到 end(不包括 end)的数组项复制到一个新的数组。
arr.splice(start[, deleteCount, elem1, …, elemN])

例子:

let arr = ["t", "e", "s", "t"];
alert( arr.slice(1, 3) ); // e,s(复制从位置 1 到位置 3 的元素)
alert( arr.slice(-2) ); // s,t(复制从位置 -2 到尾端的元素)

注:不带参数地调用它:arr.slice() 会创建一个 arr 的副本。其通常用于获取副本,以进行不影响原始数组的进一步转换。

应用场景

复制和排序数组:我们有一个字符串数组 arr。我们希望有一个排序过的副本,但保持 arr 不变。 创建一个函数 copySorted(arr) 返回这样一个副本。

我们可以使用 slice() 来创建一个副本并对其进行排序:

function copySorted(arr) {
  return arr.slice().sort();
}

let arr = ["HTML", "JavaScript", "CSS"];

let sorted = copySorted(arr);

alert( sorted ); // CSS, HTML, JavaScript
alert( arr ); // HTML, JavaScript, CSS (no changes)

concat(产生新数组)

作用:创建一个新数组,其中包含来自于其他数组和其他项的值
语法:

结果是一个包含来自于 arr,然后是 arg1,arg2 的元素的新数组。
arr.concat(arg1, arg2…)

它接受任意数量的参数 —— 数组或值都可以。
如果参数 argN 是一个数组,那么其中的所有元素都会被复制。否则,将复制参数本身。
例子:

let arr = [1, 2];
// 从 arr 和 [3,4] 创建一个新数组
alert( arr.concat([3, 4]) ); // 1,2,3,4
// 从 arr、[3,4] 和 [5,6] 创建一个新数组
alert( arr.concat([3, 4], [5, 6]) ); // 1,2,3,4,5,6
// 从 arr、[3,4]、5 和 6 创建一个新数组
alert( arr.concat([3, 4], 5, 6) ); // 1,2,3,4,5,6

通常,它只复制数组中的元素。其他对象,即使它们看起来像数组一样,但仍然会被作为一个整体添加:

let arr = [1, 2];
let arrayLike = {
  0: "something",
  length: 1
};
alert( arr.concat(arrayLike) ); // 1,2,[object Object]

但是,如果类数组对象具有 Symbol.isConcatSpreadable 属性,那么它就会被 concat 当作一个数组来处理:此对象中的元素将被添加:

let arr = [1, 2];
let arrayLike = {
  0: "something",
  1: "else",
  [Symbol.isConcatSpreadable]: true,
  length: 2
};
alert( arr.concat(arrayLike) ); // 1,2,something,else

二、遍历

forEach(不产生新数组,通过引用可以改变原数组)*

作用:遍历
语法:

arr.forEach(function(item, index, array) {
// … do something with item
});

例子:

["Bilbo", "Gandalf", "Nazgul"].forEach((item, index, array) => {
  alert(`${item} is at index ${index} in ${array}`);
});

注意事项:
1、 forEach() 方法不创建新的数组而且返回值是undefined,数组中的每个元素调用回调函数的返回值也是undefined。
2、不支持break
3、使用return无效
4、forEach只能默认从索引0开始遍历
5、forEach删除自身元素index不会被重置
(for循环过程中支持修改索引(修改 i),但forEach做不到(底层控制index自增,我们无法左右它)

let arr=[1,2,3,4,5,6];
    arr.forEach((item, index) => {  
        console.log(arr.splice(index, 1) );//依次打印[1]  [3]   [5]
        index--;//无效
    })  
    console.log(arr);//[2,4,6]

对forEach更深的理解:不可以直接修改元素,但是可以修改元素的属性
例1:

var a = [1,2,3,4,5]
a.forEach((item) => {
    item = item * 2
})
console.log(a)
// [1,2,3,4,5]

原数组并没有发生改变。

例2:

var a = [1,'1',{num:1},true]
a.forEach((item, index, arr) => {
    item = 2
})
console.log(a)
// [1,'1',{num:1},true]

这里修改item的值,依然没有修改原数组。

例3:

var a = [1,'1',{num:1},true]
a.forEach((item, index, arr) => {
    item.num = 2
    item = 2
})
console.log(a)
// [1,'1',{num:2},true]

当修改数组中对象的某个属性时,发现属性改变了。
综上:为什么会这样呢?
这里就要引入栈内存和堆内存的概念了,对于JS中的基本数据类型,如String,Number,Boolean,Undefined,Null是存在于栈内存中的,在栈内存中储存变量名及相应的值。而Object,Array,Function存在于堆内存中,在堆内存中储存变量名及引用位置。

在第一个例子中,为什么直接修改item无法修改原数组呢,因为item的值并不是相应的原数组中的值,而是重新建立的一个新变量,值和原数组相同。
在第二个例子中,数组中的对象的值也没有改变,是因为新创建的变量和原数组中的对象虽然指向同一个地址,但改变的是新变量的值,即新对象的值为2,原数组中的对象还是{num:1}。
在第三个例子中,由于对象是引用类型,新对象和旧对象指向的都是同一个地址,所以新对象把num变成了2,原数组中的对象也改变了。

正确改动原数组写法

var a = [1,2,3,4,5]
a.forEach((item, index, arr) => {
    arr[index] = item * 2
})
console.log(a)
// [2,4,6,8,10]

这个例子和例三其实同理,参数中的arr也只是原数组的一个拷贝,如果修改数组中的某一项则原数组也改变因为指向同一引用地址,而如果给参数arr赋其他值,则原数组不变。

=========================================================
补充:e.children是个对象,不能用forEach遍历!!!

还有vue的应用,还没学呜呜呜先不看了

三、在数组中搜索

indexOf和includes

作用:当数组元素是基本数据类型时,来查找搜索更方便
语法:

arr.indexOf(item, from) —— 从索引 from 开始搜索 item,如果找到则返回索引,否则返回 -1。
arr.includes(item, from) —— 从索引 from 开始搜索 item,如果找到则返回 true(译注:如果没找到,则返回 false)。

注:通常使用这些方法时只会传入一个参数:传入 item 开始搜索。默认情况下,搜索是从头开始的。

例子:

let arr = [1, 0, false];

alert( arr.indexOf(0) ); // 1
alert( arr.indexOf(false) ); // 2
alert( arr.indexOf(null) ); // -1

alert( arr.includes(1) ); // true

请注意,indexOf 和 includes 使用严格相等 === 进行比较。所以,如果我们搜索 false,它会准确找到 false 而不是数字 0。
上述两种方法一般用于简单数组,即不是对象数组这种一层包一层的。如果我们想检查数组中是否包含元素 item,并且不需要知道其确切的索引,那么 arr.includes 是首选。

方法 includes 可以正确的处理 NaN 方法
includes 的一个次要但值得注意的特性是,它可以正确处理 NaN,这与indexOf 不同:

const arr = [NaN];
alert( arr.indexOf(NaN) ); // -1(错,应该为 0)
alert(arr.includes(NaN) );// true(正确)
这是因为 includes 是在比较晚的时候才被添加到 JavaScript中的,并且在内部使用了更新了的比较算法。

find和findIndex

作用:当数组元素是复杂数据类型时,如对象数组查找搜索特定条件的对象
语法:

let result = arr.find(function(item, index, array) {
// 如果返回 true,则返回 item 并停止迭代(即只返回第一个匹配的元素)
// 对于假值(falsy)的情况,则返回 undefined
});

例子:
我们有一个存储用户的数组,每个用户都有 id 和 name 字段。让我们找到 id == 1 的那个用户:

let users = [
  {id: 1, name: "John"},
  {id: 2, name: "Pete"},
  {id: 3, name: "Mary"}
];

let user = users.find(item => item.id == 1);

alert(user.name); // John

arr.findIndex 方法(与 arr.find)具有相同的语法,但它返回找到的元素的索引,而不是元素本身。如果没找到,则返回 -1。
例子:

let users = [
  {id: 1, name: "John"},
  {id: 2, name: "Pete"},
  {id: 3, name: "Mary"},
  {id: 4, name: "John"}
];

// 寻找第一个 John 的索引
alert(users.findIndex(user => user.name == 'John')); // 0

filter(产生新数组)

作用:范围的匹配,返回所有匹配元素组成的数组
语法:

let results = arr.filter(function(item, index, array) {
// 如果 true item 被 push 到 results,迭代继续
// 如果什么都没找到,则返回空数组
});

例子:

let users = [
  {id: 1, name: "John"},
  {id: 2, name: "Pete"},
  {id: 3, name: "Mary"}
];

// 返回前两个用户的数组
let someUsers = users.filter(item => item.id < 3);

alert(someUsers.length); // 2

四、转换数组

map(产生新数组)

作用:它对数组的每个元素都调用函数,并将处理后的值返回给结果数组。
语法:

let result = arr.map(function(item, index, array) {
// 返回新值而不是当前元素
})

例子:

//将每个元素转换为它的字符串长度
let lengths = ["Bilbo", "Gandalf", "Nazgul"].map(item => item.length);
alert(lengths); // 5,7,6

sort(修改原数组)

作用:arr.sort 方法对数组进行原位排序,更改元素的顺序。
语法:

let arr = [ 1, 2, 15 ];
// 该方法重新排列 arr 的内容
arr.sort();
alert( arr ); // 1, 15, 2

这些元素默认情况下被按字符串进行排序。
故需自己提供一个函数

let arr = [ 1, 2, 15 ];

arr.sort((a, b) => a - b;);//升序

alert(arr);  // 1, 2, 15

reverse(修改原数组)

作用:反转arr中元素的顺序
例子:

let arr = [1, 2, 3, 4, 5];
arr.reverse();

alert( arr ); // 5,4,3,2,1

split(产生新数组)

作用:通过给定的分隔符将字符串分割成一个数组。
例子:

let names = 'Bilbo, Gandalf, Nazgul';

let arr = names.split(', ');

for (let name of arr) {
  alert( `A message to ${name}.` ); // A message to Bilbo(和其他名字)
}

split 方法有一个可选的第二个数字参数 —— 对数组长度的限制。如果提供了,那么额外的元素会被忽略。但实际上它很少使用:

let arr = 'Bilbo, Gandalf, Nazgul, Saruman'.split(', ', 2);

alert(arr); // Bilbo, Gandalf

可将字符串拆分成字母数组:

let str = "test";

alert( str.split('') ); // t,e,s,t

join

作用:将数组粘成字符串
例子:

let arr = ['Bilbo', 'Gandalf', 'Nazgul'];

let str = arr.join(';'); // 使用分号 ; 将数组粘合成字符串

alert( str ); // Bilbo;Gandalf;Nazgul

reduce

作用:累加
语法:

arr.reduce(callback(accumulator, currentValue,index, array),initialValue)
accumulato:上一次回调函数返回的累积值
currentValue:当前元素
index:当前元素索引值
array:调用reduce()的数组
reduce()方法initialValue参数:
initialValue: 第一次调用 callback函数时的第一个参数accumulator的值,如果没有提供初始值,则将使用数组中的第一个元素作为初始值

例子:

let arr = [1, 2, 3, 4, 5];

let result = arr.reduce((sum, current) => sum + current, 0);

alert(result); // 0+1+2+3+4+5=15

// 删除 reduce 的初始值(没有 0)
let result = arr.reduce((sum, current) => sum + current);

alert( result ); // 1+2+3+4+5=15

如果数组为空,那么在没有初始值的情况下调用 reduce 会导致错误。
例如:

let arr = [];
// Error: Reduce of empty array with no initial value
// 如果初始值存在,则 reduce 将为空 arr 返回它(即这个初始值)。
arr.reduce((sum, current) => sum + current);

所以建议始终指定初始值。

应用场景!

1、有这样一组学生数据,按需求完成工作。

    let students = [
    {
        no: 1,
        name: "张三",
        age: 18
    },
    {
        no: 2,
        name: "李四",
        age: 19
    },
    {
        no: 3,
        name: "王五",
        age: 16
    },
    {
        no: 4,
        name: "cyy",
        age: 19
    },
    {
        no: 5,
        name: "xjy",
        age: 17
    }
]

(1)将学生的信息整理成’学号+下划线+名字’,输出给老师

let student_id=students.map(item=>({//箭头函数需写(),因为返回的是对象
         id:`${item.no}_${item.name}`
    }))
    console.log(student_id);

在这里插入图片描述

(2)将学生的’学号+下划线+名字’,变成学生的id,存储进原来的students数据中

students.forEach(item=>{
    item.id=`${item.no}_${item.name}`
})
console.log(students);

在这里插入图片描述
(3)筛选出这些学生中的已经成年的学生

let adults=students.filter(item=>item.age>=18)
console.log(adults);

在这里插入图片描述

(4)根据学号找出学生资料

function findStudent(no){
        return students.find(item=>item.no==no);
    }
    let one=findStudent(1);
    console.log(one);//{no: 1, name: '张三', age: 18}

(5)找出这些学生们年龄的分布并排序

 //用includes
 let ages=[];
    students.forEach(item=>{
        if(!ages.includes(item.age)){
            ages.push(item.age);
        }
    })
    ages.sort((a,b)=>{
        return a-b;
    })
    console.log(ages);//[16, 17, 18, 19]

//用findIndex
let ages=[];
    students.forEach((item,index)=>{
        let sudentIndex=students.findIndex(stu=>item.age===stu.age)
        if(sudentIndex==index){
            ages.push(item.age)
        }
    })
    console.log(ages);

(6)计算出这些学生们的平均年龄

 let avgAge=students.reduce((sum,cur)=>{
        return sum+cur.age;
    },0)
    console.log(avgAge/students.length);//17.8

(7)统计出这些学生们各个年龄的人数

let agesObj = students.reduce((prevCounts, item)=> {
    if(item.age in prevCounts){
        // item.age是key,prevCounts[item.age]是值
        prevCounts[item.age] = prevCounts[item.age] + 1;
    } else {
        prevCounts[item.age] = 1
        }
    return prevCounts;
    },{});
    console.log(agesObj)//{16: 1, 17: 1, 18: 1, 19: 2}

=======================================================================

1、将诸如 “my-short-string” 之类的字符串由短划线分隔的单词变成骆驼式的 “myShortString”。

let str='my-dear-princess';
function camelize(str){
   return str
   .split('-')
   .map((item,index)=>index==0?item:item[0].toUpperCase()+item.slice(1))
   .join('');
}
let newstr=camelize(str);
console.log(newstr);//myDearPrincess
console.log(camelize("background-color") == 'backgroundColor'); //true

2、原位过滤范围:写一个函数 filterRangeInPlace(arr, a, b),该函数获取一个数组 arr,并删除其中介于 a 和 b 区间以外的所有值。检查:a ≤ arr[i] ≤ b。
该函数应该只修改数组。它不应该返回任何东西。
解:只能修改原数组,所以不能用filter;而涉及到数组的元素删减,也不能用forEach,故只能用for循环。

 function ilterRangeInPlace(arr, a, b){
        for(let i=0;i<arr.length;i++){
        if(arr[i]<a||arr[i]>b){
            arr.splice(i,1);
            i--;
        }
    }
let arr = [5, 3, 8, 1];

filterRangeInPlace(arr, 1, 4); // 删除 1 到 4 范围之外的值

alert( arr ); // [3, 1]

3、我们有一个字符串数组 arr。我们希望有一个排序过的副本,但保持 arr 不变。

创建一个函数 copySorted(arr) 返回这样一个副本。

//我们可以使用 slice() 来创建一个副本并对其进行排序:

function copySorted(arr) {
  return arr.slice().sort();
}

let arr = ["HTML", "JavaScript", "CSS"];

let sorted = copySorted(arr);

alert( sorted );// CSS, HTML, JavaScript
alert( arr );// HTML, JavaScript, CSS (no changes)

4、你有一个 user 对象数组,每个对象都有 user.name。编写将其转换为 names 数组的代码。

let john = { name: "John", age: 25 };
let pete = { name: "Pete", age: 30 };
let mary = { name: "Mary", age: 28 };

let users = [ john, pete, mary ];

let names = users.map(item => item.name);

alert( names ); // John, Pete, Mary

5、你有一个 user 对象数组,每个对象都有 name,surname 和 id。编写代码以该数组为基础,创建另一个具有 id 和 fullName 的对象数组,其中 fullName 由 name 和 surname 生成。

let john = { name: "John", surname: "Smith", id: 1 };
let pete = { name: "Pete", surname: "Hunt", id: 2 };
let mary = { name: "Mary", surname: "Key", id: 3 };

let users = [ john, pete, mary ];

let usersMapped = users.map(user => ({
  fullName: `${user.name} ${user.surname}`,
  id: user.id
}));

/*
usersMapped = [
  { fullName: "John Smith", id: 1 },
  { fullName: "Pete Hunt", id: 2 },
  { fullName: "Mary Key", id: 3 }
]
*/

alert( usersMapped[0].id ); // 1
alert( usersMapped[0].fullName ); // John Smith

6、按年龄对用户排序:编写函数 sortByAge(users) 获得对象数组的 age 属性,并根据 age 对这些对象数组进行排序。

function sortByAge(arr) {
  arr.sort((a, b) => a.age - b.age);
}

let john = { name: "John", age: 25 };
let pete = { name: "Pete", age: 30 };
let mary = { name: "Mary", age: 28 };

let arr = [ pete, john, mary ];

sortByAge(arr);

// 排序后的数组为:[john, mary, pete]
alert(arr[0].name); // John
alert(arr[1].name); // Mary
alert(arr[2].name); // Pete

7、假设我们收到了一个用户数组,形式为:{id:…, name:…, age:… }。

创建一个函数 groupById(arr) 从该数组创建对象,以 id 为键(key),数组项为值。
处理服务端数据时,这个函数很有用。

let users = [
  {id: 'john', name: "John Smith", age: 20},
  {id: 'ann', name: "Ann Smith", age: 24},
  {id: 'pete', name: "Pete Peterson", age: 31},
];

let usersById = groupById(users);

/*
// 调用函数后,我们应该得到:

usersById = {
  john: {id: 'john', name: "John Smith", age: 20},
  ann: {id: 'ann', name: "Ann Smith", age: 24},
  pete: {id: 'pete', name: "Pete Peterson", age: 31},
}
*/
function groupById(array) {
  return array.reduce((obj, value) => {
    obj[value.id] = value;
    return obj;
  }, {})
}
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript 数组方法有很多,每个方法都有各自的使用场景。以下是一些常见的数组方法及其使用场景: 1. `push()`:向数组末尾添加一个或多个元素。 使用场景:需要动态向数组添加元素时。 2. `pop()`:从数组末尾删除一个元素。 使用场景:需要删除数组最后一个元素时。 3. `unshift()`:向数组开头添加一个或多个元素。 使用场景:需要动态向数组开头添加元素时。 4. `shift()`:从数组开头删除一个元素。 使用场景:需要删除数组第一个元素时。 5. `splice()`:删除、插入或替换数组的元素。 使用场景:需要对数组进行复杂的操作时,如删除、插入或替换数组的元素。 6. `slice()`:截取数组的一部分元素,返回一个新数组使用场景:需要从数组获取一个子集时,但不想修改原数组。 7. `concat()`:将多个数组合并成一个新数组使用场景:需要将两个或多个数组合并为一个数组时。 8. `join()`:将数组的所有元素连接成一个字符串。 使用场景:需要将数组的元素以特定的方式连接起来时。 9. `indexOf()`:查找数组某个元素的位置。 使用场景:需要查找数组某个元素的位置时。 10. `filter()`:返回符合条件的元素组成的新数组使用场景:需要筛选数组符合某些条件的元素时。 11. `map()`:返回对每个元素进行操作后的数组使用场景:需要对数组的每个元素进行操作并返回一个新数组时。 12. `reduce()`:使用指定的函数将数组的元素合并为一个值。 使用场景:需要将数组的元素合并为一个值时,如求和、求乘积等。 以上是一些常见的数组方法及其使用场景,当然还有其他的数组方法,具体使用场景还需根据实际情况进行选择。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值