JS中对于数组的操作
一、数组基本操作
1、访问元素
array[index]
通过索引访问数组中指定位置的元素。
2、获取长度
array.length
返回数组的长度,即元素数量。常用于循环遍历数组或检查数组是否为空。
3、push() 末尾添加元素
array.push(element1, ..., elementN)
在数组末尾添加一个或多个元素。
4、pop() 末尾删除元素
array.pop()
移除数组最后一个元素并返回它。
5、unshift() 开头添加元素
array.unshift(element1, ..., elementN)
数组开头添加一个或多个元素。
6、shift() 开头删除元素
array.shift()
移除数组第一个元素并返回它。
7、concat() 合并数组
let newArray = array1.concat(array2, ..., arrayX, value1, ..., valueX);
合并两个或多个数组,返回一个新的数组。
8、copyWithin() 拷贝到另一个数组中的指定位置
copyWithin()
用于 shallow copy(浅拷贝)数组的一部分到同一数组中的另一个位置,并返回该数组,从而修改原数组。
array.copyWithin(target, start, end)
- target:必需,复制到指定目标索引处起始的位置。
- start:可选,默认为0,元素复制的起始位置。
- end:可选,默认等于数组长度,元素复制结束的位置(不包括该位置本身)。
9、fill() 填充数组
用于将一个固定值替换数组的全部或部分元素。这个方法会改变原数组,并且可以指定替换的起始位置、结束位置以及替换的值。
array.fill(value[, start[, end]])
- array:调用
fill()
方法的数组。 - value:要填充数组的值。
- start(可选):开始填充的索引位置,默认为0。
- end(可选):结束填充的索引位置(不包含该位置本身),默认为数组的长度。
注意事项
fill()
方法会直接修改原数组。- 结束索引
end
是不包含的,意味着填充不会发生在该索引位置上。 - 如果只提供
value
参数,会用该值填充整个数组。
10、includes() 查找特定元素
检查数组中是否存在指定的元素,并可选地从数组的某个索引处开始搜索。
array.includes(searchElement, fromIndex);
- searchElement:必需,需要查找的元素。
- fromIndex:可选,从该索引处开始搜索元素。默认为 0,如果为负值,则从数组长度加上 fromIndex 的值开始搜索。
11、indexOf() 查找元素索引
于查找指定值在数组中首次出现的位置或子字符串在字符串中首次出现的位置。如果找到匹配项,则返回其索引;如果没有找到,则返回 -1。
array.indexOf(searchElement, fromIndex);
- searchElement:必需,需要查找的元素。
- fromIndex:可选,从该索引处开始搜索元素,默认为0。如果为负值,则从数组长度加上 fromIndex 的值开始搜索。
12、reverse() 数组倒置
用于颠倒数组中元素的顺序。这意味着它会改变原数组,将数组中的元素按照相反的顺序重新排列。
array.reverse();
注意事项
reverse()
方法会直接修改原数组,而不是返回一个新的数组。- 对于稀疏数组(含有未定义的元素或空位的数组),
reverse()
方法可能会导致数组的空位表现得像是被删除了一样,因为反转操作会改变它们的位置。但在实践中,这种影响通常是可以忽略的。 - 如果需要保留原数组不变,可以先复制数组再进行反转,例如使用
slice()
方法创建副本:let newArray = oldArray.slice().reverse();
。
13、slice() 选取数组
用于返回数组的一部分浅拷贝,即从开始索引到结束索引(不包括结束索引)的元素。这个方法不会改变原数组,而是返回一个新的数组。
array.slice(start, end);
- array:调用
slice()
方法的数组。 - start(可选):提取片段的起始索引,从0开始。如果为负值,表示从数组末端开始计算的索引位置。省略时,从数组开头开始提取。
- end(可选):提取片段的结束索引,不包括此索引处的元素。如果省略,提取至数组末尾。如果为负值,同样表示从数组末端开始计算的索引位置。
注意事项
slice()
不会改变原数组,它总是返回一个新的数组。- 如果
start
大于end
或者end
超出了数组的长度,slice()
返回空数组。 - 省略
end
参数,或设置end
大于数组长度,都会提取直到数组的末尾。 - 负值索引从数组的末尾开始计算,
-1
表示最后一个元素,-2
表示倒数第二个元素,依此类推。
14、splice() 添加或删除元素
用于添加或删除数组中的元素,它会改变原数组。这个方法可以删除元素、插入元素或同时完成这两项操作,返回一个包含被删除元素的数组。
array.splice(start, deleteCount, item1, item2, ..., itemN);
- array:调用
splice()
方法的数组。 - start:必需,指定修改操作的开始位置,从0开始计数。如果为负值,则表示从数组末尾开始的索引位置。
- deleteCount:可选,整数,表示要删除的元素数量。如果为0或省略,则不删除任何元素。如果为负数,则不删除元素,此时该参数表示从数组末尾开始的索引位置。
- item1, …, itemN:可选,要添加进数组的元素,可以添加多个。
示例
删除元素
let months = ['Jan', 'Feb', 'Mar', 'Apr', 'May'];
months.splice(1, 2); // 从索引1开始删除2个元素
console.log(months); // 输出: ['Jan', 'May']
插入元素
months = ['Jan', 'Mar', 'May'];
months.splice(1, 0, 'Feb'); // 在索引1处插入'Feb',不删除任何元素
console.log(months); // 输出: ['Jan', 'Feb', 'Mar', 'May']
替换元素
months = ['Jan', 'Mar', 'May'];
months.splice(1, 1, 'Feb', 'Apr'); // 替换索引1处的元素,并插入'Apr'
console.log(months); // 输出: ['Jan', 'Feb', 'Apr', 'May']
注意事项
splice()
会直接修改原数组,并返回一个包含被删除元素的数组。- 如果
deleteCount
设置得比实际存在的元素数量多,只会删除实际存在的元素。 - 可以同时进行删除和插入操作,只需在删除计数后紧跟要插入的元素。
- 如果只插入元素,不删除任何元素,应将
deleteCount
设为0。
15、sort() 数组排序
用于对数组的元素进行排序。默认情况下,它会将数组元素转换为字符串,然后比较它们的UTF-16字符序列来进行排序,这可能导致不按数字或预期方式排序的结果。为了实现自定义排序逻辑,可以向 sort()
方法传递一个比较函数。
array.sort(compareFunction);
- array:调用
sort()
方法的数组。 - compareFunction(可选):自定义的比较函数,用于确定元素的排序顺序。该函数接收两个参数(数组中的元素),如果第一个参数应该排在第二个参数之前,则返回负值;如果两个元素相等,则返回0;如果第一个参数应该排在第二个参数之后,则返回正值。
示例
默认排序
let fruits = ['banana', 'apple', 'cherry'];
fruits.sort();
console.log(fruits); // 输出: ['apple', 'banana', 'cherry'],按字母顺序排序
数字排序
let numbers = [40, 100, 1, 5, 25];
numbers.sort((a, b) => a - b); // 升序
console.log(numbers); // 输出: [1, 5, 25, 40, 100]
numbers.sort((a, b) => b - a); // 降序
console.log(numbers); // 输出: [100, 40, 25, 5, 1]
注意事项
- 不传递比较函数时,默认排序行为可能不符合数字或特殊对象的排序逻辑,特别是对于数字数组,默认按字符串排序可能导致意外结果。
- 比较函数应该返回一致的结果,如果对于相同输入返回不同的结果,排序结果可能不一致。
sort()
方法会直接修改原数组,并返回排序后的数组(即返回自身)。- 对于大型数组,排序操作可能会影响性能。
自定义排序逻辑
在实际应用中,经常需要根据具体需求编写比较函数来实现自定义排序逻辑,比如按照对象的某个属性排序对象数组。
let users = [
{name: 'Alice', age: 30},
{name: 'Bob', age: 25},
{name: 'Charlie', age: 35}
];
users.sort((a, b) => a.age - b.age);
console.log(users); // 按年龄升序排序
掌握 sort()
方法和比较函数的使用,可以让你灵活地对数组进行各种排序操作。
二、遍历数组
1、forEach() 遍历数组
forEach()
是JavaScript数组的一个方法,用于遍历数组的每个元素,并对每个元素执行提供的回调函数。这个方法不会改变原数组,也不返回新的数组,它的主要用途是执行数组元素上的某种操作或者副作用,比如打印值、更新DOM等。
array.forEach(callback(currentValue, index, array) => {
// 执行的代码块
}, thisArg);
- array:调用
forEach
方法的数组。 - callback:为数组中每个元素执行的函数。
- currentValue:当前正在处理的元素。
- index(可选):当前元素在数组中的索引。
- array(可选):调用
forEach
的数组本身。
- thisArg(可选):执行回调函数时
this
的值。
注意事项
forEach()
不会跳过空元素,即使索引存在但值为undefined
或null
,也会执行回调。- 如果在遍历过程中修改了数组(比如删除元素),这可能导致未定义的行为,应尽量避免。
- 对于空数组,
forEach()
不会执行回调函数。 - 无法通过
return
语句提前终止循环,如果需要类似功能,可以使用for
循环或Array.prototype.some()
、Array.prototype.every()
等其他方法。
场景
- 遍历数组并执行简单的操作,如打印每个元素。
- 当你需要对每个元素执行异步操作(尽管需要注意它不会等待异步操作完成)。
- 执行与数组元素相关的DOM操作,如更新页面上的每个列表项。
2、map() 数组映射
map()
方法是一种遍历数组并对每个元素执行提供的函数来生成新数组的方法。这意味着原数组保持不变,而 map()
返回一个包含每次调用回调函数结果的新数组。这对于对数组中的每个元素进行转换操作非常有用,比如格式转换、计算等。
let newArray = array.map(callback(currentValue, index, array) => {
// 返回新值
}, thisArg);
- array:原数组,即调用
map()
方法的数组。 - callback:对每个元素执行的函数。
- currentValue:当前正在处理的元素。
- index(可选):当前元素在数组中的索引。
- array(可选):调用
map()
的数组本身。
- thisArg(可选):执行回调函数时
this
的值。
示例
let numbers = [1, 2, 3, 4];
// 使用 map 将数组中的每个元素乘以 2
let doubledNumbers = numbers.map(number => number * 2);
console.log(doubledNumbers); // 输出: [2, 4, 6, 8]
场景
- 类型转换:将数组中的每个元素转换为另一种类型,例如将字符串数组转换为数字数组。
- 计算操作:对数组中的每个数值执行数学运算,如加减乘除。
- 格式调整:根据需要调整数组元素的格式,如添加前缀、后缀或改变字符串大小写。
- 对象映射:将对象数组转换为另一种形式,例如提取对象的特定属性形成新数组。
注意事项
map()
不会改变原数组,而是返回一个新数组。- 如果不需要返回值或不关心映射结果,使用
forEach()
可能更合适。 - 对于空数组,
map()
会返回一个空数组,不会报错。
3、filter() 过滤数组
filter()
方法用于创建一个新的数组,新数组中的元素是通过检查指定条件并返回为 true
的所有元素组成的。这个方法对于从数组中筛选出符合特定条件的元素非常有用,而且它不会修改原始数组。
let newArray = array.filter(callback(element, index, array) => {
// 返回 true 或 false
}, thisArg);
- array:调用
filter()
方法的原数组。 - callback:一个测试条件的函数。
- element:当前正在处理的元素。
- index(可选):当前元素在数组中的索引。
- array(可选):调用
filter()
的数组本身。
- thisArg(可选):执行回调函数时
this
的上下文。
回调函数
回调函数需要返回一个布尔值:
- 如果返回
true
,当前元素会被包含在返回的新数组中。 - 如果返回
false
,当前元素会被忽略。
示例
假设我们有一个数组,想要过滤出所有的偶数:
let numbers = [1, 2, 3, 4, 5, 6];
let evenNumbers = numbers.filter(number => number % 2 === 0);
console.log(evenNumbers); // 输出: [2, 4, 6]
多个条件过滤
如果你需要基于多个条件过滤数组,只需在回调函数中加入相应的逻辑:
let items = [
{ id: 1, name: 'Alice', age: 30 },
{ id: 2, name: 'Bob', age: 25 },
{ id: 3, name: 'Charlie', age: 35 }
];
let youngAdults = items.filter(item => item.age >= 18 && item.age <= 30);
console.log(youngAdults);
注意事项
filter()
总是返回一个新数组,即使没有元素符合条件,也会返回一个空数组,而不是undefined
或null
。- 原始数组不会被修改。
- 如果数组很大,
filter()
可能会导致性能开销,因为它需要遍历整个数组。
通过结合使用 map()
和 filter()
,你可以灵活地对数组进行复杂的转换和筛选操作。
4、every() 检测数组
用于检测数组中的所有元素是否都满足某个条件。它返回一个布尔值,如果数组中的每个元素都使得测试函数返回 true
,则返回 true
,否则返回 false
。这个方法会对数组中的每个元素依次执行测试函数。
array.every(callback(element, index, array) => {
// 测试条件
}, thisArg);
- array:调用
every()
方法的数组。 - callback:测试条件的函数。
- element:当前正在处理的元素。
- index(可选):当前元素在数组中的索引。
- array(可选):调用
every()
的数组本身。
- thisArg(可选):执行回调函数时
this
的值。
示例
假设我们有一个数组,我们想检查所有元素是否都大于0:
let numbers = [2, 4, 6, 8];
let allPositive = numbers.every(number => number > 0);
console.log(allPositive); // 输出: true
numbers = [-1, 2, 3];
allPositive = numbers.every(number => number > 0);
console.log(allPositive); // 输出: false
注意事项
- 只要数组中有一个元素不满足条件,
every()
就会立即返回false
,不再检查剩余的元素。 - 空数组调用
every()
会返回true
,因为没有元素违反条件。 every()
不会改变原数组。
应用场景
- 验证数组中的所有元素是否都符合某个特定的条件,常用于表单验证、数据校验等场景。
- 在需要确保数组中的每一项都满足某个标准时使用,比如检查所有成绩是否及格、所有用户是否都已经验证邮箱等。
5、find() 查找元素
用于查找数组中满足特定条件的第一个元素。它接受一个测试函数作为参数,当数组中存在一个元素使得该测试函数返回 true
时,find()
就会返回那个元素。如果没有找到符合条件的元素,则返回 undefined
。
let foundElement = array.find(callback(element, index, array) => {
// 测试条件
}, thisArg);
- array:调用
find()
方法的数组。 - callback:测试条件的函数。
- element:当前正在处理的元素。
- index(可选):当前元素在数组中的索引。
- array(可选):调用
find()
的数组本身。
- thisArg(可选):执行回调函数时
this
的值。
回调函数
回调函数应该根据元素是否满足条件返回 true
或 false
:
- 如果回调函数返回
true
,find()
立即返回当前元素。 - 如果所有元素都不满足条件,返回
undefined
。
注意事项
find()
只返回第一个符合条件的元素,之后的元素即使也符合条件也不会被考虑。- 如果没有元素满足测试条件,
find()
返回undefined
。 find()
不会改变原数组。
应用场景
- 当需要从数组中查找第一个满足特定条件的元素时,比如在用户列表中查找第一个管理员用户、在商品列表中查找第一个打折商品等。
- 适用于任何需要根据条件快速定位数组中元素的场景。
6、findIndex() 查找元素索引
用于找出数组中满足特定条件的第一个元素的索引。它接收一个测试函数作为参数,当数组中有元素使得该测试函数返回 true
时,findIndex()
就会返回该元素的索引。如果没有找到符合条件的元素,则返回 -1
。
let index = array.findIndex(callback(element, index, array) => {
// 测试条件
}, thisArg);
- array:调用
findIndex()
方法的数组。 - callback:测试条件的函数。
- element:当前正在处理的元素。
- index(可选):当前元素在数组中的索引。
- array(可选):调用
findIndex()
的数组本身。
- thisArg(可选):执行回调函数时
this
的值。
回调函数
回调函数应该根据元素是否满足条件返回 true
或 false
:
- 如果回调函数返回
true
,findIndex()
立即返回当前元素的索引。 - 如果所有元素都不满足条件,返回
-1
。
示例
假设我们有一个数组,我们想找到第一个偶数的索引:
let numbers = [1, 3, 5, 8, 9];
let firstEvenIndex = numbers.findIndex(number => number % 2 === 0);
console.log(firstEvenIndex); // 输出: 3
注意事项
findIndex()
只返回第一个符合条件的元素的索引,之后的元素即使也符合条件也不会被考虑。- 如果没有元素满足测试条件,
findIndex()
返回-1
。 findIndex()
不会改变原数组。
应用场景
- 当需要查找数组中满足特定条件的第一个元素的位置时,例如在用户列表中查找第一个活跃用户的索引、在商品列表中找到第一个库存充足的项目的索引等。
- 适用于任何需要根据条件定位元素位置的场景。
7、reduce() 归约数组
用于对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。这个方法可以用于数组的归约,即把数组元素累积成一个单一的值,如求和、求积、求最大值、求平均值等。
array.reduce(callback(accumulator, currentValue, currentIndex, array) => {
//条件
}, initialValue)
- accumulator:累计器累加回调的返回值,在下一次迭代中作为第一个参数传给回调函数。
- currentValue:当前遍历到的数组元素。
- currentIndex(可选):当前元素的索引。默认为0,如果没有提供initialValue则从1开始。
- array:调用
reduce()
的数组本身。 - initialValue(可选):作为第一次调用callback函数时accumulator的初始值。如果省略,则accumulator的初始值为数组的第一个元素,currentValue为数组的第二个元素。
示例
求和
let sum = [1, 2, 3, 4].reduce((acc, cur) => acc + cur, 0);
console.log(sum); // 输出
8、some() 查询是否有符合元素
用于检测数组中是否有元素满足指定的测试函数。它返回一个布尔值,只要数组中有任一元素使得测试函数返回 true
,some()
就会立即返回 true
,并停止遍历。若没有元素满足条件,则返回 false
。这个方法不会改变原数组。
array.some(callback(element, index, array) => {
// 测试条件
}, thisArg);
- array:调用
some()
方法的数组。 - callback:测试条件的函数。
- element:当前正在处理的元素。
- index(可选):当前元素在数组中的索引。
- array(可选):调用
some()
的数组本身。
- thisArg(可选):执行回调函数时
this
的值。
回调函数
回调函数应该根据元素是否满足条件返回 true
或 false
:
- 如果回调函数对任何元素返回
true
,some()
立即返回true
并停止迭代。 - 如果所有元素都不满足条件,返回
false
。
示例
假设我们有一个数组,我们想知道里面是否有负数:
let numbers = [1, 2, 3, -1, 5];
let hasNegative = numbers.some(number => number < 0);
console.log(hasNegative); // 输出: true
numbers = [1, 2, 3, 4, 5];
hasNegative = numbers.some(number => number < 0);
console.log(hasNegative); // 输出: false
注意事项
some()
会尽可能少地遍历数组,一旦找到满足条件的元素就会停止。- 不会改变原数组。
- 如果数组为空,直接返回
false
。
应用场景
-
验证数组中是否存在满足特定条件的元素,如检查用户列表中是否有管理员账号、数组中是否有负数等。
-
用于早期终止遍历,当找到第一个符合条件的元素时即可停止后续不必要的检查,提高效率。
-
当你只想知道数组中是否存在满足条件的元素时,使用
some()
更合适,因为它更高效(一旦找到满足条件的元素就停止遍历)。 -
当你需要获取满足条件的第一个元素并打算进一步操作它时,应使用
find()
。
总结来说,some()
用于逻辑判断,关注“有没有”,而 find()
用于获取具体值,关注“哪一个”。